diff --git a/.clang-tidy b/.clang-tidy
index 96c8908f0c0..7617f792e03 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -66,8 +66,7 @@ Checks: >
-readability-magic-numbers,
-readability-redundant-access-specifiers,
-readability-suspicious-call-argument,
- -readability-uppercase-literal-suffix,
- -readability-use-anyofallof
+ -readability-uppercase-literal-suffix
WarningsAsErrors: '*'
HeaderFilterRegex: '(cli|gui|lib|oss-fuzz|test|triage)\/[a-z]+\.h'
CheckOptions:
diff --git a/.github/workflows/CI-cygwin.yml b/.github/workflows/CI-cygwin.yml
index 31557ecbcc7..b9ea30470da 100644
--- a/.github/workflows/CI-cygwin.yml
+++ b/.github/workflows/CI-cygwin.yml
@@ -4,7 +4,14 @@
name: CI-cygwin
-on: [push,pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/CI-mingw.yml b/.github/workflows/CI-mingw.yml
index 152e84902c2..cf64096f549 100644
--- a/.github/workflows/CI-mingw.yml
+++ b/.github/workflows/CI-mingw.yml
@@ -4,7 +4,14 @@
name: CI-mingw
-on: [push,pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/CI-unixish-docker.yml b/.github/workflows/CI-unixish-docker.yml
index 3558e6a5721..9bfc5a017b5 100644
--- a/.github/workflows/CI-unixish-docker.yml
+++ b/.github/workflows/CI-unixish-docker.yml
@@ -2,7 +2,14 @@
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: CI-unixish-docker
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/CI-unixish.yml b/.github/workflows/CI-unixish.yml
index 10cbf319d3d..44535cd077d 100644
--- a/.github/workflows/CI-unixish.yml
+++ b/.github/workflows/CI-unixish.yml
@@ -2,7 +2,14 @@
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: CI-unixish
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
@@ -334,6 +341,7 @@ jobs:
run: |
python3 -m pip install pip --upgrade
python3 -m pip install pytest
+ python3 -m pip install pytest-timeout
- name: Build cppcheck
run: |
diff --git a/.github/workflows/CI-windows.yml b/.github/workflows/CI-windows.yml
index 98df86f8558..a822cccc533 100644
--- a/.github/workflows/CI-windows.yml
+++ b/.github/workflows/CI-windows.yml
@@ -4,7 +4,14 @@
name: CI-windows
-on: [push,pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
@@ -70,6 +77,7 @@ jobs:
matrix:
os: [windows-2019, windows-2022]
arch: [x64, x86]
+ config: [debug, release]
fail-fast: false
runs-on: ${{ matrix.os }}
@@ -82,6 +90,7 @@ jobs:
- uses: actions/checkout@v3
- name: Set up Python 3.11
+ if: matrix.config == 'release'
uses: actions/setup-python@v4
with:
python-version: '3.11'
@@ -124,10 +133,12 @@ jobs:
CL: /MP
- name: Install missing Python packages
+ if: matrix.config == 'release'
run: |
python -m pip install pip --upgrade || exit /b !errorlevel!
python -m pip install pytest || exit /b !errorlevel!
python -m pip install pytest-custom_exit_code || exit /b !errorlevel!
+ python -m pip install pytest-timeout || exit /b !errorlevel!
- name: Run CMake
if: false # TODO: enable
@@ -139,6 +150,7 @@ jobs:
cmake -S . -B build -DBUILD_TESTS=On || exit /b !errorlevel!
- name: Build CLI debug configuration using MSBuild
+ if: matrix.config == 'debug'
run: |
set ARCH=${{ matrix.arch }}
if "${{ matrix.arch }}" == "x86" (
@@ -148,9 +160,11 @@ jobs:
msbuild -m cppcheck.sln /p:Configuration=Debug-PCRE;Platform=%ARCH% -maxcpucount || exit /b !errorlevel!
- name: Run Debug test
+ if: matrix.config == 'debug'
run: .\bin\debug\testrunner.exe || exit /b !errorlevel!
- name: Build CLI release configuration using MSBuild
+ if: matrix.config == 'release'
run: |
set ARCH=${{ matrix.arch }}
if "${{ matrix.arch }}" == "x86" (
@@ -160,9 +174,11 @@ jobs:
msbuild -m cppcheck.sln /p:Configuration=Release-PCRE;Platform=%ARCH% -maxcpucount || exit /b !errorlevel!
- name: Run Release test
+ if: matrix.config == 'release'
run: .\bin\testrunner.exe || exit /b !errorlevel!
- name: Run test/cli
+ if: matrix.config == 'release'
run: |
:: since FILESDIR is not set copy the binary to the root so the addons are found
:: copy .\build\bin\Release\cppcheck.exe .\cppcheck.exe || exit /b !errorlevel!
@@ -178,6 +194,7 @@ jobs:
python -m pytest test-suppress-syntaxError.py || exit /b !errorlevel!
- name: Test addons
+ if: matrix.config == 'release'
run: |
.\cppcheck --addon=threadsafety addons\test\threadsafety || exit /b !errorlevel!
.\cppcheck --addon=threadsafety --std=c++03 addons\test\threadsafety || exit /b !errorlevel!
diff --git a/.github/workflows/asan.yml b/.github/workflows/asan.yml
index c29ecde8a4a..89dc81d7cfe 100644
--- a/.github/workflows/asan.yml
+++ b/.github/workflows/asan.yml
@@ -2,7 +2,14 @@
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: address sanitizer
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/buildman.yml b/.github/workflows/buildman.yml
index 4bbdf779661..30cc5b16ad5 100644
--- a/.github/workflows/buildman.yml
+++ b/.github/workflows/buildman.yml
@@ -1,6 +1,13 @@
name: Build manual
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml
index 7bcd8bd8e31..3eda1954994 100644
--- a/.github/workflows/clang-tidy.yml
+++ b/.github/workflows/clang-tidy.yml
@@ -2,7 +2,14 @@
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: clang-tidy
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 12d15855527..f486cf9e24f 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -1,6 +1,13 @@
name: "CodeQL"
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
index b07c15811cd..5018f2c3b8a 100644
--- a/.github/workflows/coverage.yml
+++ b/.github/workflows/coverage.yml
@@ -2,7 +2,14 @@
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: Coverage
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml
index ff3134b7ed5..3ae9ceb200f 100644
--- a/.github/workflows/format.yml
+++ b/.github/workflows/format.yml
@@ -2,7 +2,14 @@
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: format
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/scriptcheck.yml b/.github/workflows/scriptcheck.yml
index 6ef6d90ee4c..d6223caafa0 100644
--- a/.github/workflows/scriptcheck.yml
+++ b/.github/workflows/scriptcheck.yml
@@ -2,7 +2,14 @@
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: scriptcheck
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/selfcheck.yml b/.github/workflows/selfcheck.yml
index 8cd028f9af9..70cc147c40f 100644
--- a/.github/workflows/selfcheck.yml
+++ b/.github/workflows/selfcheck.yml
@@ -2,7 +2,14 @@
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: selfcheck
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/tsan.yml b/.github/workflows/tsan.yml
index 876e1976141..850453aa105 100644
--- a/.github/workflows/tsan.yml
+++ b/.github/workflows/tsan.yml
@@ -2,7 +2,14 @@
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: thread sanitizer
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/ubsan.yml b/.github/workflows/ubsan.yml
index 2a422710b74..2fc169dcc23 100644
--- a/.github/workflows/ubsan.yml
+++ b/.github/workflows/ubsan.yml
@@ -2,7 +2,14 @@
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: undefined behaviour sanitizers
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/.github/workflows/valgrind.yml b/.github/workflows/valgrind.yml
index 1753e6f0acd..cf03ff89fa3 100644
--- a/.github/workflows/valgrind.yml
+++ b/.github/workflows/valgrind.yml
@@ -2,7 +2,14 @@
# Environment reference https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners
name: valgrind
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - 'main'
+ - 'releases/**'
+ tags:
+ - '2.*'
+ pull_request:
permissions:
contents: read
diff --git a/AUTHORS b/AUTHORS
index 73ff5644dd9..da05d9d1764 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -356,6 +356,7 @@ Thomas Otto
Thomas P. K. Healy
Thomas Sondergaard
Thorsten Sick
+Tim Blume
Tim Gerundt
tititiou36
Tobias Weibel
diff --git a/Makefile b/Makefile
index 8cc4ead63c8..d1aa9cc093c 100644
--- a/Makefile
+++ b/Makefile
@@ -200,6 +200,7 @@ LIBOBJ = $(libcppdir)/analyzerinfo.o \
$(libcppdir)/checkbufferoverrun.o \
$(libcppdir)/checkclass.o \
$(libcppdir)/checkcondition.o \
+ $(libcppdir)/checkersreport.o \
$(libcppdir)/checkexceptionsafety.o \
$(libcppdir)/checkfunctions.o \
$(libcppdir)/checkinternal.o \
@@ -488,6 +489,9 @@ $(libcppdir)/checkclass.o: lib/checkclass.cpp externals/tinyxml2/tinyxml2.h lib/
$(libcppdir)/checkcondition.o: lib/checkcondition.cpp lib/astutils.h lib/check.h lib/checkcondition.h lib/checkother.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.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)/checkcondition.cpp
+$(libcppdir)/checkersreport.o: lib/checkersreport.cpp lib/checkers.h lib/checkersreport.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
+ $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkersreport.cpp
+
$(libcppdir)/checkexceptionsafety.o: lib/checkexceptionsafety.cpp lib/check.h lib/checkexceptionsafety.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/sourcelocation.h lib/standards.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)/checkexceptionsafety.cpp
@@ -638,7 +642,7 @@ $(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathli
cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cmdlineparser.cpp
-cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/filelister.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
+cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/filelister.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkersreport.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutor.cpp
cli/cppcheckexecutorseh.o: cli/cppcheckexecutorseh.cpp cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/utils.h
diff --git a/addons/misra.py b/addons/misra.py
index 9c22efe218f..55de43d4887 100755
--- a/addons/misra.py
+++ b/addons/misra.py
@@ -1457,6 +1457,15 @@ def _save_ctu_summary_usage(self, dumpfile, cfg):
cppcheckdata.reportSummary(dumpfile, 'MisraUsage', names)
+ def misra_1_2(self, cfg):
+ # gcc language extensions: https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
+ for token in cfg.tokenlist:
+ if simpleMatch(token, '? :'):
+ self.reportError(token, 1, 2)
+ elif simpleMatch(token, '( {') and simpleMatch(token.next.link.previous, '; } )'):
+ self.reportError(token, 1, 2)
+
+
def misra_1_4(self, cfg):
for token in cfg.tokenlist:
if token.str in ('_Atomic', '_Noreturn', '_Generic', '_Thread_local', '_Alignas', '_Alignof'):
@@ -4311,6 +4320,7 @@ def fillVerifyExpected(verify_expected, tok):
if not self.settings.quiet:
self.printStatus('Checking %s, config %s...' % (dumpfile, cfg.name))
+ self.executeCheck(102, self.misra_1_2, cfg)
if not path_premium_addon:
self.executeCheck(104, self.misra_1_4, cfg)
self.executeCheck(202, self.misra_2_2, cfg)
diff --git a/addons/misra_9.py b/addons/misra_9.py
index f0f73371906..89002f30dfe 100644
--- a/addons/misra_9.py
+++ b/addons/misra_9.py
@@ -293,7 +293,7 @@ def parseInitializer(self, root, token):
# Fake dummy as nextChild (of current root)
nextChild = dummyRoot
- if self.token.astOperand1:
+ if nextChild and self.token.astOperand1:
self.root = nextChild
self.token = self.token.astOperand1
isFirstElement = True
@@ -328,7 +328,7 @@ def parseInitializer(self, root, token):
self.ed.parent.initializeChildren()
else:
- if self.ed.parent != self.root:
+ if self.root is not None and self.ed.parent != self.root:
# Check if token is correct value type for self.root.children[?]
child = self.root.getChildByValueElement(self.ed)
if self.token.valueType:
@@ -458,7 +458,6 @@ def misra_9_x(self, data, rule, rawTokens = None):
# without it.
if ed.valueType is None and not variable.isArray:
continue
-
parser.parseInitializer(ed, eq.astOperand2)
# print(rule, nameToken.str + '=', ed.getInitDump())
if rule == 902 and not ed.isMisra92Compliant():
diff --git a/addons/test/misra/crash_misra9_parseInitializer.c b/addons/test/misra/crash_misra9_parseInitializer.c
new file mode 100644
index 00000000000..8e3dcfd5757
--- /dev/null
+++ b/addons/test/misra/crash_misra9_parseInitializer.c
@@ -0,0 +1,18 @@
+union {
+ struct {
+ uint8_t a;
+ uint8_t b;
+ } a;
+} bar;
+
+struct foo {
+ uint8_t a;
+ union bar w;
+ uint8_t b;
+};
+
+struct foo asdf = {
+ 0,
+ {{0,0}},
+ 1
+};
diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c
index 29fadd938d6..2d1a523ffc4 100644
--- a/addons/test/misra/misra-test.c
+++ b/addons/test/misra/misra-test.c
@@ -58,6 +58,12 @@ typedef unsigned int u32;
typedef signed int s32;
typedef unsigned long long u64;
+static void misra_1_2(void)
+{
+ (void)(condition ? : 0); // 1.2
+ a = 1 + ({if (!expr) {code;} 1;}); // 1.2
+}
+
static _Atomic int misra_1_4_var; // 1.4
static _Noreturn void misra_1_4_func(void) // 1.4
{
diff --git a/addons/test/test-misra.py b/addons/test/test-misra.py
index ba1dbaae74a..3701dc2f460 100644
--- a/addons/test/test-misra.py
+++ b/addons/test/test-misra.py
@@ -120,7 +120,6 @@ def test_rules_suppression(checker, capsys):
assert found is None, 'Unexptected output:\n' + captured
dump_remove(src)
-
def test_arguments_regression():
args_ok = ["-generate-table",
"--rule-texts=./addons/test/assets/misra_rules_multiple_lines.txt",
diff --git a/clang-tidy.md b/clang-tidy.md
index b85031ac25c..ba7c7d6113d 100644
--- a/clang-tidy.md
+++ b/clang-tidy.md
@@ -87,9 +87,6 @@ We intentionally use this.
Leads to lots of "false positives". This seem to enforce a coding guidelines of certain codebases.
-`readability-use-anyofallof`
-
-We currently don't even apply our own `useStlAlgorithm` findings.
`bugprone-easily-swappable-parameters`
@@ -146,6 +143,15 @@ To be evaluated (need to remove exclusion).
`cppcoreguidelines-missing-std-forward`
`cppcoreguidelines-avoid-const-or-ref-data-members`
+`cppcoreguidelines-macro-usage`
+`cppcoreguidelines-pro-type-member-init`
+`cppcoreguidelines-pro-type-static-cast-downcast`
+`cppcoreguidelines-prefer-member-initializer`
+`cppcoreguidelines-misleading-capture-default-by-value`
+`bugprone-argument-comment.CommentBoolLiterals`
+`cert-err33-c`
+`google-readability-namespace-comments`
+`cppcoreguidelines-special-member-functions`
To be evaluated (need to enable explicitly).
diff --git a/cli/cli.vcxproj.filters b/cli/cli.vcxproj.filters
index e8385a6c84d..2b107b060f4 100644
--- a/cli/cli.vcxproj.filters
+++ b/cli/cli.vcxproj.filters
@@ -14,9 +14,6 @@
-
- Header Files
-
Header Files
@@ -44,6 +41,9 @@
Header Files
+
+ Header Files
+
@@ -76,6 +76,9 @@
Source Files
+
+ Source Files
+
diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp
index 041c051dc76..747d9cb50d5 100644
--- a/cli/cppcheckexecutor.cpp
+++ b/cli/cppcheckexecutor.cpp
@@ -20,6 +20,7 @@
#include "analyzerinfo.h"
#include "checkers.h"
+#include "checkersreport.h"
#include "cmdlineparser.h"
#include "color.h"
#include "config.h"
@@ -337,60 +338,13 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck)
return 0;
}
-static bool isCppcheckPremium(const Settings& settings) {
- return (settings.cppcheckCfgProductName.compare(0, 16, "Cppcheck Premium") == 0);
-}
-
-static std::string getMisraRuleSeverity(const std::string& rule) {
- if (checkers::misraRuleSeverity.count(rule) > 0)
- return checkers::misraRuleSeverity.at(rule);
- return "style";
-}
-
-static bool isMisraRuleInconclusive(const std::string& rule) {
- return rule == "8.3";
-}
-
-static bool isMisraRuleActive(const std::string& rule, int amendment, const std::string& severity, const Settings& settings) {
- if (!isCppcheckPremium(settings) && amendment >= 3)
- return false;
- const bool inconclusive = isMisraRuleInconclusive(rule);
- if (inconclusive && !settings.certainty.isEnabled(Certainty::inconclusive))
- return false;
- if (severity == "warning")
- return settings.severity.isEnabled(Severity::warning);
- if (severity == "style")
- return settings.severity.isEnabled(Severity::style);
- return true; // error severity
-}
-
void CppCheckExecutor::writeCheckersReport(const Settings& settings) const
{
+ CheckersReport checkersReport(settings, mActiveCheckers);
+
if (!settings.quiet) {
- int activeCheckers = 0;
- int totalCheckers = 0;
- for (const auto& checkReq: checkers::allCheckers) {
- if (mActiveCheckers.count(checkReq.first) > 0)
- ++activeCheckers;
- ++totalCheckers;
- }
- if (isCppcheckPremium(settings)) {
- for (const auto& checkReq: checkers::premiumCheckers) {
- if (mActiveCheckers.count(checkReq.first) > 0)
- ++activeCheckers;
- ++totalCheckers;
- }
- }
- if (mSettings->premiumArgs.find("misra-c-") != std::string::npos || mSettings->addons.count("misra")) {
- for (const checkers::MisraInfo& info: checkers::misraC2012Rules) {
- const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b);
- const std::string severity = getMisraRuleSeverity(rule);
- const bool active = isMisraRuleActive(rule, info.amendment, severity, settings);
- if (active)
- ++activeCheckers;
- ++totalCheckers;
- }
- }
+ const int activeCheckers = checkersReport.getActiveCheckersCount();
+ const int totalCheckers = checkersReport.getAllCheckersCount();
const std::string extra = settings.verbose ? " (use --checkers-report= to see details)" : "";
if (mCriticalErrors.empty())
@@ -403,111 +357,9 @@ void CppCheckExecutor::writeCheckersReport(const Settings& settings) const
return;
std::ofstream fout(settings.checkersReportFilename);
- if (!fout.is_open())
- return;
-
- fout << "Critical errors" << std::endl;
- fout << "---------------" << std::endl;
- if (!mCriticalErrors.empty()) {
- fout << "There was critical errors (" << mCriticalErrors << ")" << std::endl;
- fout << "All checking is skipped for a file with such error" << std::endl;
- } else {
- fout << "No critical errors, all files were checked." << std::endl;
- fout << "Important: Analysis is still not guaranteed to be 'complete' it is possible there are false negatives." << std::endl;
- }
-
- fout << std::endl << std::endl;
- fout << "Open source checkers" << std::endl;
- fout << "--------------------" << std::endl;
+ if (fout.is_open())
+ fout << checkersReport.getReport(mCriticalErrors);
- int maxCheckerSize = 0;
- for (const auto& checkReq: checkers::allCheckers) {
- const std::string& checker = checkReq.first;
- if (checker.size() > maxCheckerSize)
- maxCheckerSize = checker.size();
- }
- for (const auto& checkReq: checkers::allCheckers) {
- const std::string& checker = checkReq.first;
- const bool active = mActiveCheckers.count(checkReq.first) > 0;
- const std::string& req = checkReq.second;
- fout << (active ? "Yes " : "No ") << checker;
- if (!active && !req.empty())
- fout << std::string(maxCheckerSize + 4 - checker.size(), ' ') << "require:" + req;
- fout << std::endl;
- }
-
- const bool cppcheckPremium = isCppcheckPremium(settings);
-
- if (cppcheckPremium) {
- fout << std::endl << std::endl;
- fout << "Premium checkers" << std::endl;
- fout << "----------------" << std::endl;
-
- maxCheckerSize = 0;
- for (const auto& checkReq: checkers::premiumCheckers) {
- const std::string& checker = checkReq.first;
- if (checker.size() > maxCheckerSize)
- maxCheckerSize = checker.size();
- }
- for (const auto& checkReq: checkers::premiumCheckers) {
- const std::string& checker = checkReq.first;
- std::string req = checkReq.second;
- bool active = cppcheckPremium;
- if (req == "warning")
- active &= mSettings->severity.isEnabled(Severity::warning);
- else if (req == "style")
- active &= mSettings->severity.isEnabled(Severity::style);
- fout << (active ? "Yes " : "No ") << checker;
- if (!req.empty())
- req = "premium," + req;
- else
- req = "premium";
- if (!active)
- fout << std::string(maxCheckerSize + 4 - checker.size(), ' ') << "require:" + req;
- fout << std::endl;
- }
- }
-
- int misra = 0;
- if (mSettings->premiumArgs.find("misra-c-2012") != std::string::npos)
- misra = 2012;
- else if (mSettings->premiumArgs.find("misra-c-2023") != std::string::npos)
- misra = 2023;
- else if (mSettings->addons.count("misra"))
- misra = 2012;
-
- if (misra == 0) {
- fout << std::endl << std::endl;
- fout << "Misra C" << std::endl;
- fout << "-------" << std::endl;
- fout << "Misra is not enabled" << std::endl;
- } else {
- fout << std::endl << std::endl;
- fout << "Misra C " << misra << std::endl;
- fout << "------------" << std::endl;
- for (const checkers::MisraInfo& info: checkers::misraC2012Rules) {
- const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b);
- const std::string severity = getMisraRuleSeverity(rule);
- const bool active = isMisraRuleActive(rule, info.amendment, severity, settings);
- const bool inconclusive = isMisraRuleInconclusive(rule);
- fout << (active ? "Yes " : "No ") << rule;
- std::string extra;
- if (misra == 2012 && info.amendment >= 1)
- extra = " amendment:" + std::to_string(info.amendment);
- std::string reqs;
- if (info.amendment >= 3)
- reqs += ",premium";
- if (severity != "error")
- reqs += "," + severity;
- if (inconclusive)
- reqs += ",inconclusive";
- if (!active && !reqs.empty())
- extra += " require:" + reqs.substr(1);
- if (!extra.empty())
- fout << std::string(7 - rule.size(), ' ') << extra;
- fout << '\n';
- }
- }
}
bool CppCheckExecutor::loadLibraries(Settings& settings)
@@ -607,7 +459,7 @@ void CppCheckExecutor::reportErr(const ErrorMessage &msg)
{
assert(mSettings != nullptr);
- if (msg.severity == Severity::none && msg.id == "logChecker") {
+ if (msg.severity == Severity::none && (msg.id == "logChecker" || endsWith(msg.id, "-logChecker"))) {
const std::string& checker = msg.shortMessage();
mActiveCheckers.emplace(checker);
return;
@@ -692,6 +544,12 @@ bool CppCheckExecutor::executeCommand(std::string exe, std::vector
{
output_.clear();
+#ifdef _WIN32
+ // Extra quoutes are needed in windows if filename has space
+ if (exe.find(" ") != std::string::npos)
+ exe = "\"" + exe + "\"";
+#endif
+
std::string joinedArgs;
for (const std::string &arg : args) {
if (!joinedArgs.empty())
@@ -702,21 +560,34 @@ bool CppCheckExecutor::executeCommand(std::string exe, std::vector
joinedArgs += arg;
}
-#ifdef _WIN32
- // Extra quoutes are needed in windows if filename has space
- if (exe.find(" ") != std::string::npos)
- exe = "\"" + exe + "\"";
const std::string cmd = exe + " " + joinedArgs + " " + redirect;
- std::unique_ptr pipe(_popen(cmd.c_str(), "r"), _pclose);
+
+#ifdef _WIN32
+ FILE* p = _popen(cmd.c_str(), "r");
#else
- const std::string cmd = exe + " " + joinedArgs + " " + redirect;
- std::unique_ptr pipe(popen(cmd.c_str(), "r"), pclose);
+ FILE *p = popen(cmd.c_str(), "r");
#endif
- if (!pipe)
+ if (!p) {
+ // TODO: read errno
return false;
+ }
char buffer[1024];
- while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr)
+ while (fgets(buffer, sizeof(buffer), p) != nullptr)
output_ += buffer;
+
+#ifdef _WIN32
+ const int res = _pclose(p);
+#else
+ const int res = pclose(p);
+#endif
+ if (res == -1) { // error occured
+ // TODO: read errno
+ return false;
+ }
+ if (res != 0) { // process failed
+ // TODO: need to get error details
+ return false;
+ }
return true;
}
diff --git a/createrelease b/createrelease
index 0a98f850266..1373f44aee6 100755
--- a/createrelease
+++ b/createrelease
@@ -45,6 +45,7 @@
#
# Update the Makefile:
# make dmake && ./dmake --release
+# Uppdatera CI så att dmake körs med --release
# git commit -a -m "2.8: Updated Makefile"
#
# Tag:
diff --git a/gui/checkstatistics.cpp b/gui/checkstatistics.cpp
index a8f75c9a8f1..4f812b8ee43 100644
--- a/gui/checkstatistics.cpp
+++ b/gui/checkstatistics.cpp
@@ -65,6 +65,11 @@ void CheckStatistics::addItem(const QString &tool, ShowTypes::ShowType type)
}
}
+void CheckStatistics::addChecker(const QString &checker)
+{
+ mActiveCheckers.insert(checker.toStdString());
+}
+
void CheckStatistics::clear()
{
mStyle.clear();
@@ -73,6 +78,8 @@ void CheckStatistics::clear()
mPortability.clear();
mInformation.clear();
mError.clear();
+ mActiveCheckers.clear();
+ mCheckersReport.clear();
}
unsigned CheckStatistics::getCount(const QString &tool, ShowTypes::ShowType type) const
diff --git a/gui/checkstatistics.h b/gui/checkstatistics.h
index f487c39c854..d53be128834 100644
--- a/gui/checkstatistics.h
+++ b/gui/checkstatistics.h
@@ -23,9 +23,13 @@
#include
#include
+#include
#include
#include
+#include
+#include
+
/// @addtogroup GUI
/// @{
@@ -44,6 +48,11 @@ class CheckStatistics : public QObject {
*/
void addItem(const QString &tool, ShowTypes::ShowType type);
+ /**
+ * @brief Add checker to statistics
+ */
+ void addChecker(const QString& checker);
+
/**
* @brief Clear the statistics.
*
@@ -59,9 +68,24 @@ class CheckStatistics : public QObject {
*/
unsigned getCount(const QString &tool, ShowTypes::ShowType type) const;
+ std::set getActiveCheckers() const {
+ return mActiveCheckers;
+ }
+
+ int getNumberOfActiveCheckers() const {
+ return mActiveCheckers.size();
+ }
+
/** Get tools with results */
QStringList getTools() const;
+ void setCheckersReport(QString report) {
+ mCheckersReport = std::move(report);
+ }
+ QString getCheckersReport() const {
+ return mCheckersReport;
+ }
+
private:
QMap mStyle;
QMap mWarning;
@@ -69,6 +93,8 @@ class CheckStatistics : public QObject {
QMap mPortability;
QMap mInformation;
QMap mError;
+ std::set mActiveCheckers;
+ QString mCheckersReport;
};
/// @}
diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp
index 5f28d8b98cf..fb3a3081f49 100644
--- a/gui/mainwindow.cpp
+++ b/gui/mainwindow.cpp
@@ -540,6 +540,7 @@ void MainWindow::doAnalyzeProject(ImportProject p, const bool checkLibrary, cons
}
mThread->setProject(p);
mThread->check(checkSettings);
+ mUI->mResults->setCheckSettings(checkSettings);
}
void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrary, const bool checkConfiguration)
@@ -603,6 +604,7 @@ void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrar
mThread->setCheckFiles(true);
mThread->check(checkSettings);
+ mUI->mResults->setCheckSettings(checkSettings);
}
void MainWindow::analyzeCode(const QString& code, const QString& filename)
@@ -1208,7 +1210,9 @@ void MainWindow::reAnalyzeSelected(const QStringList& files)
// considered in "Modified Files Check" performed after "Selected Files Check"
// TODO: Should we store per file CheckStartTime?
QDateTime saveCheckStartTime = mThread->getCheckStartTime();
- mThread->check(getCppcheckSettings());
+ const Settings& checkSettings = getCppcheckSettings();
+ mThread->check(checkSettings);
+ mUI->mResults->setCheckSettings(checkSettings);
mThread->setCheckStartTime(saveCheckStartTime);
}
@@ -1232,7 +1236,9 @@ void MainWindow::reAnalyze(bool all)
qDebug() << "Rechecking project file" << mProjectFile->getFilename();
mThread->setCheckFiles(all);
- mThread->check(getCppcheckSettings());
+ const Settings& checkSettings = getCppcheckSettings();
+ mThread->check(checkSettings);
+ mUI->mResults->setCheckSettings(checkSettings);
}
void MainWindow::clearResults()
diff --git a/gui/mainwindow.h b/gui/mainwindow.h
index 78782b22bdd..969e1c28e9d 100644
--- a/gui/mainwindow.h
+++ b/gui/mainwindow.h
@@ -193,7 +193,7 @@ public slots:
/** @brief Slot for showing the library editor */
void showLibraryEditor();
-protected slots:
+private slots:
/** @brief Slot for checkthread's done signal */
void analysisDone();
diff --git a/gui/resultsview.cpp b/gui/resultsview.cpp
index e1cea88330b..891d80a4973 100644
--- a/gui/resultsview.cpp
+++ b/gui/resultsview.cpp
@@ -19,6 +19,7 @@
#include "resultsview.h"
#include "checkstatistics.h"
+#include "checkersreport.h"
#include "codeeditor.h"
#include "codeeditorstyle.h"
#include "common.h"
@@ -105,6 +106,7 @@ void ResultsView::initialize(QSettings *settings, ApplicationList *list, ThreadH
ResultsView::~ResultsView()
{
delete mUI;
+ delete mCheckSettings;
}
void ResultsView::clear(bool results)
@@ -116,6 +118,8 @@ void ResultsView::clear(bool results)
mUI->mDetails->setText(QString());
mStatistics->clear();
+ delete mCheckSettings;
+ mCheckSettings = nullptr;
//Clear the progressbar
mUI->mProgress->setMaximum(PROGRESS_MAX);
@@ -150,6 +154,11 @@ void ResultsView::progress(int value, const QString& description)
void ResultsView::error(const ErrorItem &item)
{
+ if (item.severity == Severity::none && (item.errorId == "logChecker" || item.errorId.endsWith("-logChecker"))) {
+ mStatistics->addChecker(item.message);
+ return;
+ }
+
handleCriticalError(item);
if (mUI->mTree->addErrorItem(item)) {
@@ -282,6 +291,13 @@ QString ResultsView::getCheckDirectory()
return mUI->mTree->getCheckDirectory();
}
+void ResultsView::setCheckSettings(const Settings &settings)
+{
+ delete mCheckSettings;
+ mCheckSettings = new Settings;
+ *mCheckSettings = settings;
+}
+
void ResultsView::checkingStarted(int count)
{
mSuccess = true;
@@ -296,6 +312,13 @@ void ResultsView::checkingFinished()
mUI->mProgress->setVisible(false);
mUI->mProgress->setFormat("%p%");
+ {
+ Settings checkSettings;
+ const std::set activeCheckers = mStatistics->getActiveCheckers();
+ CheckersReport checkersReport(mCheckSettings ? *mCheckSettings : checkSettings, activeCheckers);
+ mStatistics->setCheckersReport(QString::fromStdString(checkersReport.getReport(mCriticalErrors.toStdString())));
+ }
+
// TODO: Items can be mysteriously hidden when checking is finished, this function
// call should be redundant but it "unhides" the wrongly hidden items.
mUI->mTree->refreshTree();
@@ -528,6 +551,11 @@ void ResultsView::stopAnalysis()
void ResultsView::handleCriticalError(const ErrorItem &item)
{
if (ErrorLogger::isCriticalErrorId(item.errorId.toStdString())) {
+ if (!mCriticalErrors.contains(item.errorId)) {
+ if (!mCriticalErrors.isEmpty())
+ mCriticalErrors += ",";
+ mCriticalErrors += item.errorId;
+ }
QString msg = tr("There was a critical error with id '%1'").arg(item.errorId);
if (!item.file0.isEmpty())
msg += ", " + tr("when checking %1").arg(item.file0);
diff --git a/gui/resultsview.h b/gui/resultsview.h
index 70c8ddfa2b9..d978afab936 100644
--- a/gui/resultsview.h
+++ b/gui/resultsview.h
@@ -29,6 +29,7 @@
#include
class ErrorItem;
+class Settings;
class ApplicationList;
class ThreadHandler;
class QModelIndex;
@@ -136,6 +137,11 @@ class ResultsView : public QWidget {
QString getCheckDirectory();
+ /**
+ * Set settings used in checking
+ */
+ void setCheckSettings(const Settings& settings);
+
/**
* @brief Inform the view that checking has started
*
@@ -368,11 +374,16 @@ public slots:
CheckStatistics *mStatistics;
+ Settings* mCheckSettings = nullptr;
+
/**
* Set to true when checking finish successfully. Set to false whenever analysis starts.
*/
bool mSuccess = false;
+ /** Critical error ids */
+ QString mCriticalErrors;
+
private slots:
/**
* @brief Custom context menu for Analysis Log
diff --git a/gui/statsdialog.cpp b/gui/statsdialog.cpp
index 4f5ce9a85bf..5dfd8a589e0 100644
--- a/gui/statsdialog.cpp
+++ b/gui/statsdialog.cpp
@@ -75,6 +75,10 @@ StatsDialog::StatsDialog(QWidget *parent)
{
mUI->setupUi(this);
+ QFont font("courier");
+ font.setStyleHint(QFont::Monospace);
+ mUI->mCheckersReport->setFont(font);
+
setWindowFlags(Qt::Window);
connect(mUI->mCopyToClipboard, &QPushButton::pressed, this, &StatsDialog::copyToClipboard);
@@ -366,12 +370,14 @@ void StatsDialog::copyToClipboard()
void StatsDialog::setStatistics(const CheckStatistics *stats)
{
mStatistics = stats;
- mUI->mLblErrors->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowErrors)));
- mUI->mLblWarnings->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowWarnings)));
- mUI->mLblStyle->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowStyle)));
- mUI->mLblPortability->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowPortability)));
- mUI->mLblPerformance->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowPerformance)));
- mUI->mLblInformation->setText(QString("%1").arg(stats->getCount(CPPCHECK,ShowTypes::ShowInformation)));
+ mUI->mLblErrors->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowErrors)));
+ mUI->mLblWarnings->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowWarnings)));
+ mUI->mLblStyle->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowStyle)));
+ mUI->mLblPortability->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowPortability)));
+ mUI->mLblPerformance->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowPerformance)));
+ mUI->mLblInformation->setText(QString::number(stats->getCount(CPPCHECK,ShowTypes::ShowInformation)));
+ mUI->mLblActiveCheckers->setText(QString::number(stats->getNumberOfActiveCheckers()));
+ mUI->mCheckersReport->setPlainText(stats->getCheckersReport());
}
#ifdef QT_CHARTS_LIB
diff --git a/gui/statsdialog.ui b/gui/statsdialog.ui
index 8147b8e7ec6..a749c51e676 100644
--- a/gui/statsdialog.ui
+++ b/gui/statsdialog.ui
@@ -6,8 +6,8 @@
0
0
- 502
- 274
+ 500
+ 414
@@ -247,114 +247,150 @@
Statistics
-
+
-
-
-
-
-
-
- Errors:
-
-
-
- -
-
-
- TextLabel
-
-
-
-
+
+
+ Errors:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
-
-
-
-
-
-
- Warnings:
-
-
-
- -
-
-
- TextLabel
-
-
-
-
+
+
+ Warnings:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
-
-
-
-
-
-
- Stylistic warnings:
-
-
-
- -
-
-
- TextLabel
-
-
-
-
+
+
+ Stylistic warnings:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
-
-
-
-
-
-
- Portability warnings:
-
-
-
- -
-
-
- TextLabel
-
-
-
-
+
+
+ Portability warnings:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
-
-
-
-
-
-
- Performance issues:
-
-
-
- -
-
-
- TextLabel
-
-
-
-
+
+
+ Performance issues:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
-
-
-
-
-
-
- Information messages:
-
-
-
- -
-
-
- TextLabel
-
-
-
-
+
+
+ Information messages:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
+
+ -
+
+
+ Active checkers:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ TextLabel
+
+
+
+
+
+
+
+ Checkers
+
+
+ -
+
+
+ true
+
+
+
+ Courier 10 Pitch
+
+
+
+ true
+
+
+ true
+
+
diff --git a/lib/astutils.cpp b/lib/astutils.cpp
index 53de61dcc26..b238827dad1 100644
--- a/lib/astutils.cpp
+++ b/lib/astutils.cpp
@@ -984,6 +984,7 @@ bool isAliasOf(const Token *tok, nonneg int varid, bool* inconclusive)
{
if (tok->varId() == varid)
return false;
+ // NOLINTNEXTLINE(readability-use-anyofallof) - TODO: fix this / also Cppcheck false negative
for (const ValueFlow::Value &val : tok->values()) {
if (!val.isLocalLifetimeValue())
continue;
@@ -1000,29 +1001,43 @@ bool isAliasOf(const Token *tok, nonneg int varid, bool* inconclusive)
return false;
}
-bool isAliasOf(const Token* tok, const Token* expr, bool* inconclusive)
+bool isAliasOf(const Token* tok, const Token* expr, int* indirect, bool* inconclusive)
{
- const bool pointer = astIsPointer(tok);
const ValueFlow::Value* value = nullptr;
- const Token* r = findAstNode(expr, [&](const Token* childTok) {
- for (const ValueFlow::Value& val : tok->values()) {
- if (val.isImpossible())
- continue;
- if (val.isLocalLifetimeValue() || (pointer && val.isSymbolicValue() && val.intvalue == 0)) {
- if (findAstNode(val.tokvalue,
- [&](const Token* aliasTok) {
- return aliasTok->exprId() == childTok->exprId();
- })) {
- if (val.isInconclusive() && inconclusive != nullptr) {
- value = &val;
- } else {
- return true;
+ const Token* r = nullptr;
+ if (indirect)
+ *indirect = 1;
+ for (const ReferenceToken& ref : followAllReferences(tok)) {
+ const bool pointer = astIsPointer(ref.token);
+ r = findAstNode(expr, [&](const Token* childTok) {
+ if (childTok->exprId() == 0)
+ return false;
+ if (ref.token != tok && expr->exprId() == childTok->exprId()) {
+ if (indirect)
+ *indirect = 0;
+ return true;
+ }
+ for (const ValueFlow::Value& val : ref.token->values()) {
+ if (val.isImpossible())
+ continue;
+ if (val.isLocalLifetimeValue() || (pointer && val.isSymbolicValue() && val.intvalue == 0)) {
+ if (findAstNode(val.tokvalue,
+ [&](const Token* aliasTok) {
+ return aliasTok->exprId() == childTok->exprId();
+ })) {
+ if (val.isInconclusive() && inconclusive != nullptr) {
+ value = &val;
+ } else {
+ return true;
+ }
}
}
}
- }
- return false;
- });
+ return false;
+ });
+ if (r)
+ break;
+ }
if (!r && value && inconclusive)
*inconclusive = true;
return r || value;
@@ -1465,6 +1480,8 @@ bool isUsedAsBool(const Token* const tok, const Settings* settings)
if (isForLoopCondition(tok))
return true;
if (!Token::Match(parent, "%cop%")) {
+ if (parent->str() == "," && parent->isInitComma())
+ return false;
std::vector vtParents = getParentValueTypes(tok, settings);
return std::any_of(vtParents.cbegin(), vtParents.cend(), [&](const ValueType& vt) {
return vt.pointer == 0 && vt.type == ValueType::BOOL;
@@ -2725,16 +2742,17 @@ static bool isExpressionChangedAt(const F& getExprTok,
if (globalvar && !tok->isKeyword() && Token::Match(tok, "%name% (") && !(tok->function() && tok->function()->isAttributePure()))
// TODO: Is global variable really changed by function call?
return true;
+ int i = 1;
bool aliased = false;
// If we can't find the expression then assume it is an alias
auto expr = getExprTok();
if (!expr)
aliased = true;
if (!aliased)
- aliased = isAliasOf(tok, expr);
+ aliased = isAliasOf(tok, expr, &i);
if (!aliased)
return false;
- if (isVariableChanged(tok, indirect + 1, settings, cpp, depth))
+ if (isVariableChanged(tok, indirect + i, settings, cpp, depth))
return true;
// TODO: Try to traverse the lambda function
if (Token::Match(tok, "%var% ("))
diff --git a/lib/astutils.h b/lib/astutils.h
index fdcc713d767..95a8896a6de 100644
--- a/lib/astutils.h
+++ b/lib/astutils.h
@@ -356,7 +356,7 @@ bool isExpressionChangedAt(const Token* expr,
/// If token is an alias if another variable
bool isAliasOf(const Token *tok, nonneg int varid, bool* inconclusive = nullptr);
-bool isAliasOf(const Token* tok, const Token* expr, bool* inconclusive = nullptr);
+bool isAliasOf(const Token* tok, const Token* expr, int* indirect = nullptr, bool* inconclusive = nullptr);
bool isAliased(const Variable *var);
diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp
index dd15ca06641..49613c06914 100644
--- a/lib/checkclass.cpp
+++ b/lib/checkclass.cpp
@@ -988,6 +988,14 @@ void CheckClass::initializeVarList(const Function &func, std::listisConst() && !member->isStatic()) {
assignAllVar(usage);
}
+
+ // const method, assume it assigns all mutable members
+ else if (member->isConst()) {
+ for (Usage& i: usage) {
+ if (i.var->isMutable())
+ i.assign = true;
+ }
+ }
}
// not member function
diff --git a/lib/checkers.h b/lib/checkers.h
index 5cc61a518a3..5acdba8f4f0 100644
--- a/lib/checkers.h
+++ b/lib/checkers.h
@@ -206,22 +206,395 @@ namespace checkers {
static std::map premiumCheckers{
- {"CheckBufferOverrun::addressOfPointerArithmetic","warning"},
- {"CheckBufferOverrun::negativeBufferSizeCheckedNonZero","warning"},
- {"CheckBufferOverrun::negativeBufferSizeCheckedNonZero","warning"},
- {"CheckHang::infiniteLoop",""},
- {"CheckHang::infiniteLoopContinue",""},
- {"CheckOther::arrayPointerComparison","style"},
- {"CheckOther::knownResult","style"},
- {"CheckOther::lossOfPrecision","style"},
- {"CheckOther::pointerCast","style"},
- {"CheckOther::reassignInLoop","style"},
- {"CheckOther::unreachableCode","style"},
- {"CheckStrictAlias::strictAliasCondition","warning"},
- {"CheckUninitVar::uninitvar",""},
- {"CheckUninitVar::uninitmember",""},
- {"CheckUnusedVar::unreadVariable","style"},
- {"CheckUnusedVar::unusedPrivateMember","style"},
+ {"Autosar: A0-1-3","style"},
+ {"Autosar: A0-4-2","style"},
+ {"Autosar: A0-4-4","style"},
+ {"Autosar: A10-1-1","style"},
+ {"Autosar: A11-0-2","style"},
+ {"Autosar: A11-3-1","style"},
+ {"Autosar: A13-2-1","style"},
+ {"Autosar: A13-2-3","style"},
+ {"Autosar: A13-5-2","style"},
+ {"Autosar: A13-5-5","style"},
+ {"Autosar: A15-1-2","style"},
+ {"Autosar: A15-3-5","style"},
+ {"Autosar: A16-6-1","style"},
+ {"Autosar: A16-7-1","style"},
+ {"Autosar: A18-0-3","style"},
+ {"Autosar: A18-1-1","style"},
+ {"Autosar: A18-1-2","style"},
+ {"Autosar: A18-1-3","style"},
+ {"Autosar: A18-5-1","style"},
+ {"Autosar: A18-9-1","style"},
+ {"Autosar: A2-11-1","style"},
+ {"Autosar: A2-13-1","style"},
+ {"Autosar: A2-13-3","style"},
+ {"Autosar: A2-13-5","style"},
+ {"Autosar: A2-13-6","style"},
+ {"Autosar: A2-5-2","style"},
+ {"Autosar: A3-1-3","style"},
+ {"Autosar: A3-1-4","style"},
+ {"Autosar: A3-3-1","style"},
+ {"Autosar: A4-10-1","style"},
+ {"Autosar: A4-7-1","style"},
+ {"Autosar: A5-0-2","style"},
+ {"Autosar: A5-0-3","style"},
+ {"Autosar: A5-0-4","style"},
+ {"Autosar: A5-1-1","style"},
+ {"Autosar: A5-1-2","style"},
+ {"Autosar: A5-1-3","style"},
+ {"Autosar: A5-16-1","style"},
+ {"Autosar: A5-1-6","style"},
+ {"Autosar: A5-1-7","style"},
+ {"Autosar: A5-2-1","style"},
+ {"Autosar: A5-2-4","style"},
+ {"Autosar: A6-5-3","style"},
+ {"Autosar: A7-1-4","style"},
+ {"Autosar: A7-1-6","style"},
+ {"Autosar: A7-1-7","style"},
+ {"Autosar: A8-4-1","style"},
+ {"Autosar: A8-5-3","style"},
+ {"Autosar: A9-3-1","style"},
+ {"Cert C: ARR30-C","warning"},
+ {"Cert C: ARR32-C","warning"},
+ {"Cert C: ARR37-C","warning"},
+ {"Cert C: ARR38-C",""},
+ {"Cert C: ARR39-C","warning"},
+ {"Cert C: CON30-C","style"},
+ {"Cert C: CON31-C","style"},
+ {"Cert C: CON32-C","style"},
+ {"Cert C: CON33-C","style"},
+ {"Cert C: CON34-C","warning"},
+ {"Cert C: CON35-C","warning"},
+ {"Cert C: CON36-C","style"},
+ {"Cert C: CON37-C","style"},
+ {"Cert C: CON38-C","warning"},
+ {"Cert C: CON39-C","warning"},
+ {"Cert C: CON40-C","warning"},
+ {"Cert C: CON41-C","style"},
+ {"Cert C++: CON51-CPP",""},
+ {"Cert C++: CON52-CPP","style"},
+ {"Cert C++: CON53-CPP","style"},
+ {"Cert C++: CON54-CPP","style"},
+ {"Cert C++: CON55-CPP","style"},
+ {"Cert C++: CON56-CPP",""},
+ {"Cert C++: CTR50-CPP",""},
+ {"Cert C++: CTR52-CPP",""},
+ {"Cert C++: CTR53-CPP",""},
+ {"Cert C++: CTR56-CPP","style"},
+ {"Cert C++: CTR57-CPP",""},
+ {"Cert C++: CTR58-CPP",""},
+ {"Cert C: DCL31-C","style"},
+ {"Cert C: DCL36-C","style"},
+ {"Cert C: DCL37-C","style"},
+ {"Cert C: DCL38-C","style"},
+ {"Cert C: DCL39-C","style"},
+ {"Cert C: DCL40-C","style"},
+ {"Cert C: DCL41-C","style"},
+ {"Cert C++: DCL50-CPP","style"},
+ {"Cert C++: DCL51-CPP","style"},
+ {"Cert C++: DCL52-CPP","style"},
+ {"Cert C++: DCL53-CPP","style"},
+ {"Cert C++: DCL54-CPP",""},
+ {"Cert C++: DCL56-CPP",""},
+ {"Cert C++: DCL58-CPP","style"},
+ {"Cert C++: DCL59-CPP","style"},
+ {"Cert C: ENV30-C","style"},
+ {"Cert C: ENV31-C","style"},
+ {"Cert C: ENV32-C","style"},
+ {"Cert C: ENV33-C","style"},
+ {"Cert C: ENV34-C","style"},
+ {"Cert C: ERR30-C","warning"},
+ {"Cert C: ERR32-C","warning"},
+ {"Cert C: ERR33-C","warning"},
+ {"Cert C++: ERR50-CPP",""},
+ {"Cert C++: ERR51-CPP","style"},
+ {"Cert C++: ERR52-CPP","style"},
+ {"Cert C++: ERR53-CPP",""},
+ {"Cert C++: ERR54-CPP",""},
+ {"Cert C++: ERR55-CPP",""},
+ {"Cert C++: ERR56-CPP",""},
+ {"Cert C++: ERR58-CPP",""},
+ {"Cert C++: ERR59-CPP","warning"},
+ {"Cert C++: ERR60-CPP","warning"},
+ {"Cert C++: ERR61-CPP","style"},
+ {"Cert C++: ERR62-CPP","style"},
+ {"Cert C: EXP32-C","warning"},
+ {"Cert C: EXP35-C",""},
+ {"Cert C: EXP36-C","style"},
+ {"Cert C: EXP37-C","style"},
+ {"Cert C: EXP39-C","style"},
+ {"Cert C: EXP40-C","style"},
+ {"Cert C: EXP42-C","style"},
+ {"Cert C: EXP43-C","style"},
+ {"Cert C: EXP45-C","warning"},
+ {"Cert C++: EXP50-CPP",""},
+ {"Cert C++: EXP51-CPP",""},
+ {"Cert C++: EXP55-CPP",""},
+ {"Cert C++: EXP56-CPP",""},
+ {"Cert C++: EXP57-CPP","style"},
+ {"Cert C++: EXP58-CPP","style"},
+ {"Cert C++: EXP59-CPP",""},
+ {"Cert C: FIO30-C","warning"},
+ {"Cert C: FIO32-C","style"},
+ {"Cert C: FIO34-C","style"},
+ {"Cert C: FIO37-C",""},
+ {"Cert C: FIO38-C","style"},
+ {"Cert C: FIO40-C","style"},
+ {"Cert C: FIO41-C","style"},
+ {"Cert C: FIO44-C","warning"},
+ {"Cert C: FIO45-C","warning"},
+ {"Cert C++: FIO51-CPP","style"},
+ {"Cert C: FLP30-C","warning"},
+ {"Cert C: FLP36-C","portability"},
+ {"Cert C: FLP37-C","style"},
+ {"Cert C: INT30-C","warning"},
+ {"Cert C: INT31-C","warning"},
+ {"Cert C: INT32-C","warning"},
+ {"Cert C: INT33-C","warning"},
+ {"Cert C: INT34-C","warning"},
+ {"Cert C: INT35-C","warning"},
+ {"Cert C: INT36-C","warning"},
+ {"Cert C++: INT50-CPP","style"},
+ {"Cert C: MEM33-C","style"},
+ {"Cert C: MEM35-C","warning"},
+ {"Cert C: MEM36-C","warning"},
+ {"Cert C++: MEM52-CPP",""},
+ {"Cert C++: MEM53-CPP",""},
+ {"Cert C++: MEM54-CPP",""},
+ {"Cert C++: MEM55-CPP",""},
+ {"Cert C++: MEM57-CPP","style"},
+ {"Cert C: MSC30-C","style"},
+ {"Cert C: MSC32-C","style"},
+ {"Cert C: MSC33-C","style"},
+ {"Cert C: MSC38-C","warning"},
+ {"Cert C: MSC39-C","warning"},
+ {"Cert C: MSC40-C","warning"},
+ {"Cert C++: MSC50-CPP","style"},
+ {"Cert C++: MSC51-CPP","style"},
+ {"Cert C++: MSC53-CPP",""},
+ {"Cert C++: MSC54-CPP","style"},
+ {"Cert C++: OOP51-CPP",""},
+ {"Cert C++: OOP55-CPP",""},
+ {"Cert C++: OOP56-CPP",""},
+ {"Cert C++: OOP57-CPP",""},
+ {"Cert C++: OOP58-CPP","style"},
+ {"Cert C: PRE31-C","style"},
+ {"Cert C: SIG30-C","style"},
+ {"Cert C: SIG31-C","warning"},
+ {"Cert C: SIG34-C","style"},
+ {"Cert C: SIG35-C","warning"},
+ {"Cert C: STR31-C","warning"},
+ {"Cert C: STR32-C","warning"},
+ {"Cert C: STR34-C","warning"},
+ {"Cert C: STR38-C","style"},
+ {"Cert C++: STR50-CPP",""},
+ {"Cert C++: STR53-CPP",""},
+ {"Misra C: 10.1","style"},
+ {"Misra C: 10.2","style"},
+ {"Misra C: 10.3","style"},
+ {"Misra C: 10.4","style"},
+ {"Misra C: 10.5","style"},
+ {"Misra C: 10.6","style"},
+ {"Misra C: 10.7","style"},
+ {"Misra C: 10.8","style"},
+ {"Misra C: 11.10","style"},
+ {"Misra C: 12.6",""},
+ {"Misra C: 1.5","style"},
+ {"Misra C: 17.10","style"},
+ {"Misra C: 17.11","style"},
+ {"Misra C: 17.12","style"},
+ {"Misra C: 17.9","style"},
+ {"Misra C: 18.10","style"},
+ {"Misra C: 18.9","style"},
+ {"Misra C: 21.12","style"},
+ {"Misra C: 21.22","style"},
+ {"Misra C: 21.23","style"},
+ {"Misra C: 21.24","style"},
+ {"Misra C: 21.25","warning"},
+ {"Misra C: 21.26","warning"},
+ {"Misra C: 22.11",""},
+ {"Misra C: 22.12","style"},
+ {"Misra C: 22.13","style"},
+ {"Misra C: 22.14","style"},
+ {"Misra C: 22.15","style"},
+ {"Misra C: 22.16","warning"},
+ {"Misra C: 22.17","warning"},
+ {"Misra C: 22.18","warning"},
+ {"Misra C: 22.19","warning"},
+ {"Misra C: 22.20","style"},
+ {"Misra C: 23.1","style"},
+ {"Misra C: 23.2","style"},
+ {"Misra C: 23.3","style"},
+ {"Misra C: 23.4","style"},
+ {"Misra C: 23.5","style"},
+ {"Misra C: 23.6","style"},
+ {"Misra C: 23.7","style"},
+ {"Misra C: 23.8","style"},
+ {"Misra C: 6.3","style"},
+ {"Misra C: 7.5","style"},
+ {"Misra C: 7.6","style"},
+ {"Misra C: 8.10","style"},
+ {"Misra C: 8.15","style"},
+ {"Misra C: 8.16","style"},
+ {"Misra C: 8.17","style"},
+ {"Misra C: 9.6","style"},
+ {"Misra C: 9.7",""},
+ {"Misra C++: M0-1-11","style"},
+ {"Misra C++: M0-1-12","style"},
+ {"Misra C++: M0-1-4","style"},
+ {"Misra C++: M0-1-5","style"},
+ {"Misra C++: M0-1-7","style"},
+ {"Misra C++: M0-1-8","style"},
+ {"Misra C++: M10-1-1","style"},
+ {"Misra C++: M10-1-2","style"},
+ {"Misra C++: M10-1-3","style"},
+ {"Misra C++: M10-2-1","style"},
+ {"Misra C++: M10-3-3","style"},
+ {"Misra C++: M11-0-1","style"},
+ {"Misra C++: M12-8-2","style"},
+ {"Misra C++: M14-5-1","warning"},
+ {"Misra C++: M14-5-2","warning"},
+ {"Misra C++: M14-5-3","warning"},
+ {"Misra C++: M14-6-1","warning"},
+ {"Misra C++: M14-7-1","style"},
+ {"Misra C++: M14-7-2","style"},
+ {"Misra C++: M15-0-3",""},
+ {"Misra C++: M15-1-1",""},
+ {"Misra C++: M15-1-2","style"},
+ {"Misra C++: M15-1-3","style"},
+ {"Misra C++: M15-3-2","warning"},
+ {"Misra C++: M15-3-3",""},
+ {"Misra C++: M15-4-1","style"},
+ {"Misra C++: M16-0-1","style"},
+ {"Misra C++: M16-0-2","style"},
+ {"Misra C++: M16-0-3","style"},
+ {"Misra C++: M16-0-4","style"},
+ {"Misra C++: M16-1-1","style"},
+ {"Misra C++: M16-2-1","style"},
+ {"Misra C++: M16-2-2","style"},
+ {"Misra C++: M16-2-3","style"},
+ {"Misra C++: M16-2-4","style"},
+ {"Misra C++: M16-2-5","style"},
+ {"Misra C++: M16-2-6","style"},
+ {"Misra C++: M16-3-1","style"},
+ {"Misra C++: M16-3-2","style"},
+ {"Misra C++: M17-0-1","style"},
+ {"Misra C++: M17-0-2","style"},
+ {"Misra C++: M17-0-3","style"},
+ {"Misra C++: M17-0-5","style"},
+ {"Misra C++: M18-0-1","style"},
+ {"Misra C++: M18-0-2","style"},
+ {"Misra C++: M18-0-3","style"},
+ {"Misra C++: M18-0-4","style"},
+ {"Misra C++: M18-0-5","style"},
+ {"Misra C++: M18-2-1","style"},
+ {"Misra C++: M18-4-1","style"},
+ {"Misra C++: M18-7-1","style"},
+ {"Misra C++: M19-3-1","style"},
+ {"Misra C++: M2-10-1","style"},
+ {"Misra C++: M2-10-3","style"},
+ {"Misra C++: M2-10-4","style"},
+ {"Misra C++: M2-10-5","style"},
+ {"Misra C++: M2-10-6","style"},
+ {"Misra C++: M2-13-4","style"},
+ {"Misra C++: M2-13-5","style"},
+ {"Misra C++: M27-0-1","style"},
+ {"Misra C++: M2-7-1","style"},
+ {"Misra C++: M2-7-2","style"},
+ {"Misra C++: M2-7-3","style"},
+ {"Misra C++: M3-1-1","style"},
+ {"Misra C++: M3-1-2","style"},
+ {"Misra C++: M3-1-3","style"},
+ {"Misra C++: M3-2-1",""},
+ {"Misra C++: M3-3-1","style"},
+ {"Misra C++: M3-3-2","style"},
+ {"Misra C++: M3-9-1","style"},
+ {"Misra C++: M3-9-2","style"},
+ {"Misra C++: M3-9-3","style"},
+ {"Misra C++: M4-10-1","style"},
+ {"Misra C++: M4-10-2","style"},
+ {"Misra C++: M4-5-1","style"},
+ {"Misra C++: M4-5-2","style"},
+ {"Misra C++: M4-5-3","style"},
+ {"Misra C++: M5-0-10","style"},
+ {"Misra C++: M5-0-11","style"},
+ {"Misra C++: M5-0-12","style"},
+ {"Misra C++: M5-0-14","style"},
+ {"Misra C++: M5-0-15","style"},
+ {"Misra C++: M5-0-20","style"},
+ {"Misra C++: M5-0-21","style"},
+ {"Misra C++: M5-0-2","style"},
+ {"Misra C++: M5-0-3","style"},
+ {"Misra C++: M5-0-4","style"},
+ {"Misra C++: M5-0-5","style"},
+ {"Misra C++: M5-0-6","style"},
+ {"Misra C++: M5-0-7","style"},
+ {"Misra C++: M5-0-8","style"},
+ {"Misra C++: M5-0-9","style"},
+ {"Misra C++: M5-2-10","style"},
+ {"Misra C++: M5-2-11","style"},
+ {"Misra C++: M5-2-12","style"},
+ {"Misra C++: M5-2-1","style"},
+ {"Misra C++: M5-2-2","style"},
+ {"Misra C++: M5-2-3","style"},
+ {"Misra C++: M5-2-5","style"},
+ {"Misra C++: M5-2-6","style"},
+ {"Misra C++: M5-2-7","style"},
+ {"Misra C++: M5-2-8","style"},
+ {"Misra C++: M5-2-9","style"},
+ {"Misra C++: M5-3-1","style"},
+ {"Misra C++: M5-3-2","style"},
+ {"Misra C++: M5-3-3","style"},
+ {"Misra C++: M6-2-3","style"},
+ {"Misra C++: M6-4-4","style"},
+ {"Misra C++: M6-4-6","style"},
+ {"Misra C++: M6-4-7","style"},
+ {"Misra C++: M6-4-8","style"},
+ {"Misra C++: M6-5-1","style"},
+ {"Misra C++: M6-5-2","style"},
+ {"Misra C++: M6-5-3","style"},
+ {"Misra C++: M6-5-4","style"},
+ {"Misra C++: M6-5-5","style"},
+ {"Misra C++: M6-5-6","style"},
+ {"Misra C++: M6-6-1","style"},
+ {"Misra C++: M6-6-3","style"},
+ {"Misra C++: M6-6-4","style"},
+ {"Misra C++: M6-6-5","style"},
+ {"Misra C++: M7-2-1","style"},
+ {"Misra C++: M7-3-1","style"},
+ {"Misra C++: M7-3-2","style"},
+ {"Misra C++: M7-3-3","style"},
+ {"Misra C++: M7-3-4","style"},
+ {"Misra C++: M7-3-5","style"},
+ {"Misra C++: M7-3-6","style"},
+ {"Misra C++: M7-4-2","style"},
+ {"Misra C++: M7-4-3","style"},
+ {"Misra C++: M7-5-3","style"},
+ {"Misra C++: M8-0-1","style"},
+ {"Misra C++: M8-3-1","style"},
+ {"Misra C++: M8-4-4","style"},
+ {"Misra C++: M9-3-1","style"},
+ {"Misra C++: M9-5-1","style"},
+ {"Misra C++: M9-6-2","style"},
+ {"Misra C++: M9-6-3","style"},
+ {"Misra C++: M9-6-4","style"},
+ {"PremiumCheckBufferOverrun::addressOfPointerArithmetic","warning"},
+ {"PremiumCheckBufferOverrun::negativeBufferSizeCheckedNonZero","warning"},
+ {"PremiumCheckBufferOverrun::negativeBufferSizeCheckedNonZero","warning"},
+ {"PremiumCheckHang::infiniteLoop",""},
+ {"PremiumCheckHang::infiniteLoopContinue",""},
+ {"PremiumCheckOther::arrayPointerComparison","style"},
+ {"PremiumCheckOther::knownResult","style"},
+ {"PremiumCheckOther::lossOfPrecision","style"},
+ {"PremiumCheckOther::pointerCast","style"},
+ {"PremiumCheckOther::reassignInLoop","style"},
+ {"PremiumCheckOther::unreachableCode","style"},
+ {"PremiumCheckStrictAlias::strictAliasCondition","warning"},
+ {"PremiumCheckUninitVar::uninitmember",""},
+ {"PremiumCheckUninitVar::uninitvar",""},
+ {"PremiumCheckUnusedVar::unreadVariable","style"},
+ {"PremiumCheckUnusedVar::unusedPrivateMember","style"},
};
diff --git a/lib/checkersreport.cpp b/lib/checkersreport.cpp
new file mode 100644
index 00000000000..f3649503efb
--- /dev/null
+++ b/lib/checkersreport.cpp
@@ -0,0 +1,223 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2023 Cppcheck team.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "checkersreport.h"
+#include "checkers.h"
+#include
+
+static bool isCppcheckPremium(const Settings& settings) {
+ return (settings.cppcheckCfgProductName.compare(0, 16, "Cppcheck Premium") == 0);
+}
+
+static std::string getMisraRuleSeverity(const std::string& rule) {
+ if (checkers::misraRuleSeverity.count(rule) > 0)
+ return checkers::misraRuleSeverity.at(rule);
+ return "style";
+}
+
+static bool isMisraRuleInconclusive(const std::string& rule) {
+ return rule == "8.3";
+}
+
+static bool isMisraRuleActive(const std::string& rule, int amendment, const std::string& severity, const Settings& settings) {
+ if (!isCppcheckPremium(settings) && amendment >= 3)
+ return false;
+ const bool inconclusive = isMisraRuleInconclusive(rule);
+ if (inconclusive && !settings.certainty.isEnabled(Certainty::inconclusive))
+ return false;
+ if (severity == "warning")
+ return settings.severity.isEnabled(Severity::warning);
+ if (severity == "style")
+ return settings.severity.isEnabled(Severity::style);
+ return true; // error severity
+}
+
+CheckersReport::CheckersReport(const Settings& settings, const std::set& activeCheckers)
+ : mSettings(settings), mActiveCheckers(activeCheckers)
+{}
+
+int CheckersReport::getActiveCheckersCount()
+{
+ if (mAllCheckersCount == 0) {
+ countCheckers();
+ }
+ return mActiveCheckersCount;
+}
+
+int CheckersReport::getAllCheckersCount()
+{
+ if (mAllCheckersCount == 0) {
+ countCheckers();
+ }
+ return mAllCheckersCount;
+}
+
+void CheckersReport::countCheckers()
+{
+ mActiveCheckersCount = mAllCheckersCount = 0;
+
+ for (const auto& checkReq: checkers::allCheckers) {
+ if (mActiveCheckers.count(checkReq.first) > 0)
+ ++mActiveCheckersCount;
+ ++mAllCheckersCount;
+ }
+ for (const auto& checkReq: checkers::premiumCheckers) {
+ if (mActiveCheckers.count(checkReq.first) > 0)
+ ++mActiveCheckersCount;
+ ++mAllCheckersCount;
+ }
+ if (mSettings.premiumArgs.find("misra-c-") != std::string::npos || mSettings.addons.count("misra")) {
+ for (const checkers::MisraInfo& info: checkers::misraC2012Rules) {
+ const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b);
+ const std::string severity = getMisraRuleSeverity(rule);
+ const bool active = isMisraRuleActive(rule, info.amendment, severity, mSettings);
+ if (active)
+ ++mActiveCheckersCount;
+ ++mAllCheckersCount;
+ }
+ }
+}
+
+std::string CheckersReport::getReport(const std::string& criticalErrors) const
+{
+ std::ostringstream fout;
+
+ fout << "Critical errors" << std::endl;
+ fout << "---------------" << std::endl;
+ if (!criticalErrors.empty()) {
+ fout << "There was critical errors (" << criticalErrors << ")" << std::endl;
+ fout << "All checking is skipped for a file with such error" << std::endl;
+ } else {
+ fout << "No critical errors, all files were checked." << std::endl;
+ fout << "Important: Analysis is still not guaranteed to be 'complete' it is possible there are false negatives." << std::endl;
+ }
+
+ fout << std::endl << std::endl;
+ fout << "Open source checkers" << std::endl;
+ fout << "--------------------" << std::endl;
+
+ int maxCheckerSize = 0;
+ for (const auto& checkReq: checkers::allCheckers) {
+ const std::string& checker = checkReq.first;
+ if (checker.size() > maxCheckerSize)
+ maxCheckerSize = checker.size();
+ }
+ for (const auto& checkReq: checkers::allCheckers) {
+ const std::string& checker = checkReq.first;
+ const bool active = mActiveCheckers.count(checkReq.first) > 0;
+ const std::string& req = checkReq.second;
+ fout << (active ? "Yes " : "No ") << checker;
+ if (!active && !req.empty())
+ fout << std::string(maxCheckerSize + 4 - checker.size(), ' ') << "require:" + req;
+ fout << std::endl;
+ }
+
+ const bool cppcheckPremium = isCppcheckPremium(mSettings);
+
+ auto reportSection = [&fout, cppcheckPremium]
+ (const std::string& title,
+ const Settings& settings,
+ const std::set& activeCheckers,
+ const std::map& premiumCheckers,
+ const std::string& substring) {
+ fout << std::endl << std::endl;
+ fout << title << std::endl;
+ fout << std::string(title.size(), '-') << std::endl;
+ if (!cppcheckPremium) {
+ fout << "Not available, Cppcheck Premium is not used" << std::endl;
+ return;
+ }
+ int maxCheckerSize = 0;
+ for (const auto& checkReq: premiumCheckers) {
+ const std::string& checker = checkReq.first;
+ if (checker.find(substring) != std::string::npos && checker.size() > maxCheckerSize)
+ maxCheckerSize = checker.size();
+ }
+ for (const auto& checkReq: premiumCheckers) {
+ const std::string& checker = checkReq.first;
+ if (checker.find(substring) == std::string::npos)
+ continue;
+ std::string req = checkReq.second;
+ bool active = cppcheckPremium && activeCheckers.count(checker) > 0;
+ if (req == "warning")
+ active &= settings.severity.isEnabled(Severity::warning);
+ else if (req == "style")
+ active &= settings.severity.isEnabled(Severity::style);
+ else if (!req.empty())
+ active = false; // FIXME: handle req
+ fout << (active ? "Yes " : "No ") << checker;
+ if (!req.empty())
+ req = "premium," + req;
+ else
+ req = "premium";
+ if (!active)
+ fout << std::string(maxCheckerSize + 4 - checker.size(), ' ') << "require:" + req;
+ fout << std::endl;
+ }
+ };
+
+ reportSection("Premium checkers", mSettings, mActiveCheckers, checkers::premiumCheckers, "::");
+ reportSection("Autosar", mSettings, mActiveCheckers, checkers::premiumCheckers, "Autosar: ");
+ reportSection("Cert C", mSettings, mActiveCheckers, checkers::premiumCheckers, "Cert C: ");
+ reportSection("Cert C++", mSettings, mActiveCheckers, checkers::premiumCheckers, "Cert C++: ");
+
+ int misra = 0;
+ if (mSettings.premiumArgs.find("misra-c-2012") != std::string::npos)
+ misra = 2012;
+ else if (mSettings.premiumArgs.find("misra-c-2023") != std::string::npos)
+ misra = 2023;
+ else if (mSettings.addons.count("misra"))
+ misra = 2012;
+
+ if (misra == 0) {
+ fout << std::endl << std::endl;
+ fout << "Misra C" << std::endl;
+ fout << "-------" << std::endl;
+ fout << "Misra is not enabled" << std::endl;
+ } else {
+ fout << std::endl << std::endl;
+ fout << "Misra C " << misra << std::endl;
+ fout << "------------" << std::endl;
+ for (const checkers::MisraInfo& info: checkers::misraC2012Rules) {
+ const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b);
+ const std::string severity = getMisraRuleSeverity(rule);
+ const bool active = isMisraRuleActive(rule, info.amendment, severity, mSettings);
+ const bool inconclusive = isMisraRuleInconclusive(rule);
+ fout << (active ? "Yes " : "No ") << rule;
+ std::string extra;
+ if (misra == 2012 && info.amendment >= 1)
+ extra = " amendment:" + std::to_string(info.amendment);
+ std::string reqs;
+ if (info.amendment >= 3)
+ reqs += ",premium";
+ if (severity != "error")
+ reqs += "," + severity;
+ if (inconclusive)
+ reqs += ",inconclusive";
+ if (!active && !reqs.empty())
+ extra += " require:" + reqs.substr(1);
+ if (!extra.empty())
+ fout << std::string(7 - rule.size(), ' ') << extra;
+ fout << '\n';
+ }
+ }
+
+ reportSection("Misra C++ 2008", mSettings, mActiveCheckers, checkers::premiumCheckers, "Misra C++: ");
+
+ return fout.str();
+}
diff --git a/lib/checkersreport.h b/lib/checkersreport.h
new file mode 100644
index 00000000000..b6acab8800b
--- /dev/null
+++ b/lib/checkersreport.h
@@ -0,0 +1,44 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2023 Cppcheck team.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#include "settings.h"
+#include
+#include
+
+class CPPCHECKLIB CheckersReport {
+public:
+ CheckersReport(const Settings& settings, const std::set& activeCheckers);
+
+ int getActiveCheckersCount();
+ int getAllCheckersCount();
+
+ std::string getReport(const std::string& criticalErrors) const;
+
+private:
+ const Settings& mSettings;
+ const std::set& mActiveCheckers;
+
+ void countCheckers();
+
+ int mActiveCheckersCount = 0;
+ int mAllCheckersCount = 0;
+};
+
+
diff --git a/lib/checkother.cpp b/lib/checkother.cpp
index e75688e9542..13ae85df44d 100644
--- a/lib/checkother.cpp
+++ b/lib/checkother.cpp
@@ -3704,8 +3704,7 @@ static bool isVariableExpression(const Token* tok)
return isVariableExpression(tok->astOperand1()) &&
isVariableExpression(tok->astOperand2());
if (Token::simpleMatch(tok, "["))
- return isVariableExpression(tok->astOperand1()) &&
- tok->astOperand2() && tok->astOperand2()->hasKnownIntValue();
+ return isVariableExpression(tok->astOperand1());
return false;
}
@@ -3764,11 +3763,17 @@ void CheckOther::checkKnownArgument()
mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true))
continue;
// ensure that there is a integer variable in expression with unknown value
- const Token* vartok = findAstNode(tok, [](const Token* child) {
+ const Token* vartok = nullptr;
+ visitAstNodes(tok, [&](const Token* child) {
if (Token::Match(child, "%var%|.|[")) {
- return astIsIntegral(child, false) && !astIsPointer(child) && child->values().empty();
+ if (child->hasKnownIntValue())
+ return ChildrenToVisit::none;
+ if (astIsIntegral(child, false) && !astIsPointer(child) && child->values().empty()) {
+ vartok = child;
+ return ChildrenToVisit::done;
+ }
}
- return false;
+ return ChildrenToVisit::op1_and_op2;
});
if (!vartok)
continue;
diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp
index fe9b6005034..481617d3489 100644
--- a/lib/cppcheck.cpp
+++ b/lib/cppcheck.cpp
@@ -315,8 +315,8 @@ static void createDumpFile(const Settings& settings,
break;
}
- fdump << "" << std::endl;
- fdump << "" << std::endl;
+ fdump << "\n";
+ fdump << "\n";
fdump << " \n";
+ << "/>" << '\n';
}
static std::string executeAddon(const AddonInfo &addonInfo,
@@ -352,6 +352,14 @@ static std::string executeAddon(const AddonInfo &addonInfo,
#endif
for (const char* py_exe : py_exes) {
std::string out;
+#ifdef _MSC_VER
+ // FIXME: hack to avoid debug assertion with _popen() in executeCommand() for non-existing commands
+ const std::string cmd = std::string(py_exe) + " --version >NUL";
+ if (system(cmd.c_str()) != 0) {
+ // TODO: get more detailed error?
+ break;
+ }
+#endif
if (executeCommand(py_exe, split("--version"), redirect, out) && out.compare(0, 7, "Python ") == 0 && std::isdigit(out[7])) {
pythonExe = py_exe;
break;
@@ -373,7 +381,7 @@ static std::string executeAddon(const AddonInfo &addonInfo,
std::string result;
if (!executeCommand(pythonExe, split(args), redirect, result)) {
- std::string message("Failed to execute addon (command: '" + pythonExe + " " + args + "'). Exitcode is nonzero.");
+ std::string message("Failed to execute addon '" + addonInfo.name + "' (command: '" + pythonExe + " " + args + "'). Exitcode is nonzero.");
if (result.size() > 2) {
message = message + "\n" + message + "\nOutput:\n" + result;
message.resize(message.find_last_not_of("\n\r"));
@@ -571,16 +579,16 @@ unsigned int CppCheck::check(const std::string &path)
std::string dumpFile;
createDumpFile(mSettings, path, fdump, dumpFile);
if (fdump.is_open()) {
- fdump << "" << std::endl;
+ fdump << "\n";
for (const ErrorMessage& errmsg: compilerWarnings)
fdump << " \n";
- fdump << " " << std::endl;
- fdump << " " << std::endl;
- fdump << " " << std::endl;
- fdump << " " << std::endl;
+ fdump << " \n";
+ fdump << " \n";
+ fdump << " \n";
+ fdump << " \n";
tokenizer.dump(fdump);
- fdump << "" << std::endl;
- fdump << "" << std::endl;
+ fdump << "\n";
+ fdump << "\n";
fdump.close();
}
@@ -588,13 +596,12 @@ unsigned int CppCheck::check(const std::string &path)
executeAddons(dumpFile);
} catch (const InternalError &e) {
- internalError(path, e.errorMessage);
- mExitCode = 1; // e.g. reflect a syntax error
+ internalError(path, "Processing Clang AST dump failed: " + e.errorMessage);
} catch (const TerminateException &) {
// Analysis is terminated
return mExitCode;
} catch (const std::exception &e) {
- internalError(path, e.what());
+ internalError(path, std::string("Processing Clang AST dump failed: ") + e.what());
}
return mExitCode;
@@ -975,22 +982,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
return mExitCode;
} catch (const InternalError &e) {
- std::list locationList;
- if (e.token) {
- locationList.emplace_back(e.token, &tokenizer.list);
- } else {
- locationList.emplace_back(filename, 0, 0);
- if (filename != tokenizer.list.getSourceFilePath()) {
- locationList.emplace_back(tokenizer.list.getSourceFilePath(), 0, 0);
- }
- }
- ErrorMessage errmsg(std::move(locationList),
- tokenizer.list.getSourceFilePath(),
- Severity::error,
- e.errorMessage,
- e.id,
- Certainty::normal);
-
+ ErrorMessage errmsg = ErrorMessage::fromInternalError(e, &tokenizer.list, filename);
reportErr(errmsg);
}
}
@@ -1026,12 +1018,11 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
// Analysis is terminated
return mExitCode;
} catch (const std::runtime_error &e) {
- internalError(filename, e.what());
- } catch (const std::bad_alloc &e) {
- internalError(filename, e.what());
+ internalError(filename, std::string("Checking file failed: ") + e.what());
+ } catch (const std::bad_alloc &) {
+ internalError(filename, "Checking file failed: out of memory");
} catch (const InternalError &e) {
- internalError(filename, e.errorMessage);
- mExitCode=1; // e.g. reflect a syntax error
+ internalError(filename, "Checking file failed: " + e.errorMessage);
}
if (!mSettings.buildDir.empty()) {
@@ -1050,9 +1041,10 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
return mExitCode;
}
+// TODO: replace with ErrorMessage::fromInternalError()
void CppCheck::internalError(const std::string &filename, const std::string &msg)
{
- const std::string fullmsg("Bailing out from checking since there was an internal error: " + msg);
+ const std::string fullmsg("Bailing out from analysis: " + msg);
const ErrorMessage::FileLocation loc1(filename, 0, 0);
std::list callstack(1, loc1);
@@ -1500,9 +1492,11 @@ void CppCheck::executeAddons(const std::vector& files)
errmsg.setmsg(text);
const std::string severity = obj["severity"].get();
errmsg.severity = Severity::fromString(severity);
- if (errmsg.severity == Severity::SeverityType::none)
- continue;
- if (!mSettings.severity.isEnabled(errmsg.severity))
+ if (errmsg.severity == Severity::SeverityType::none) {
+ if (!endsWith(errmsg.id, "-logChecker"))
+ continue;
+ }
+ else if (!mSettings.severity.isEnabled(errmsg.severity))
continue;
errmsg.file0 = ((files.size() == 1) ? files[0] : "");
@@ -1525,8 +1519,7 @@ void CppCheck::executeAddonsWholeProgram(const std::map
+
@@ -122,6 +123,7 @@
+
diff --git a/lib/cppcheck.vcxproj.filters b/lib/cppcheck.vcxproj.filters
index 2bba20684fa..c3e5d34664f 100644
--- a/lib/cppcheck.vcxproj.filters
+++ b/lib/cppcheck.vcxproj.filters
@@ -194,6 +194,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
@@ -406,6 +412,15 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp
index 5b69bd489f6..af322cb0210 100644
--- a/lib/errorlogger.cpp
+++ b/lib/errorlogger.cpp
@@ -45,6 +45,7 @@ const std::set ErrorLogger::mCriticalErrorIds{
"internalAstError",
"instantiationError",
"internalError",
+ "premium-internalError",
"preprocessorErrorDirective",
"syntaxError",
"unknownMacro"
@@ -230,6 +231,32 @@ static void serializeString(std::string &oss, const std::string & str)
oss += str;
}
+ErrorMessage ErrorMessage::fromInternalError(const InternalError &internalError, const TokenList *tokenList, const std::string &filename)
+{
+ if (internalError.token)
+ assert(tokenList != nullptr); // we need to make sure we can look up the provided token
+
+ std::list locationList;
+ if (tokenList && internalError.token) {
+ ErrorMessage::FileLocation loc(internalError.token, tokenList);
+ locationList.push_back(std::move(loc));
+ } else {
+ ErrorMessage::FileLocation loc2(filename, 0, 0);
+ locationList.push_back(std::move(loc2));
+ if (tokenList && (filename != tokenList->getSourceFilePath())) {
+ ErrorMessage::FileLocation loc(tokenList->getSourceFilePath(), 0, 0);
+ locationList.push_back(std::move(loc));
+ }
+ }
+ ErrorMessage errmsg(std::move(locationList),
+ tokenList ? tokenList->getSourceFilePath() : filename,
+ Severity::error,
+ internalError.errorMessage,
+ internalError.id,
+ Certainty::normal);
+ return errmsg;
+}
+
std::string ErrorMessage::serialize() const
{
// Serialize this message into a simple string
@@ -731,36 +758,36 @@ std::string ErrorMessage::FileLocation::stringify() const
std::string ErrorLogger::toxml(const std::string &str)
{
- std::ostringstream xml;
+ std::string xml;
for (const unsigned char c : str) {
switch (c) {
case '<':
- xml << "<";
+ xml += "<";
break;
case '>':
- xml << ">";
+ xml += ">";
break;
case '&':
- xml << "&";
+ xml += "&";
break;
case '\"':
- xml << """;
+ xml += """;
break;
case '\'':
- xml << "'";
+ xml += "'";
break;
case '\0':
- xml << "\\0";
+ xml += "\\0";
break;
default:
if (c >= ' ' && c <= 0x7f)
- xml << c;
+ xml += c;
else
- xml << 'x';
+ xml += 'x';
break;
}
}
- return xml.str();
+ return xml;
}
std::string ErrorLogger::plistHeader(const std::string &version, const std::vector &files)
diff --git a/lib/errorlogger.h b/lib/errorlogger.h
index ae0466ce5b6..2d1bed3c4f5 100644
--- a/lib/errorlogger.h
+++ b/lib/errorlogger.h
@@ -198,6 +198,8 @@ class CPPCHECKLIB ErrorMessage {
return mSymbolNames;
}
+ static ErrorMessage fromInternalError(const InternalError &internalError, const TokenList *tokenList, const std::string &filename);
+
private:
static std::string fixInvalidChars(const std::string& raw);
diff --git a/lib/lib.pri b/lib/lib.pri
index 09676f2dede..6c31cc91c34 100644
--- a/lib/lib.pri
+++ b/lib/lib.pri
@@ -16,6 +16,7 @@ HEADERS += $${PWD}/analyzer.h \
$${PWD}/checkbufferoverrun.h \
$${PWD}/checkclass.h \
$${PWD}/checkcondition.h \
+ $${PWD}/checkersreport.h \
$${PWD}/checkexceptionsafety.h \
$${PWD}/checkfunctions.h \
$${PWD}/checkinternal.h \
@@ -85,6 +86,7 @@ SOURCES += $${PWD}/analyzerinfo.cpp \
$${PWD}/checkbufferoverrun.cpp \
$${PWD}/checkclass.cpp \
$${PWD}/checkcondition.cpp \
+ $${PWD}/checkersreport.cpp \
$${PWD}/checkexceptionsafety.cpp \
$${PWD}/checkfunctions.cpp \
$${PWD}/checkinternal.cpp \
diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp
index 01d2a94f142..9628dc0c6a0 100644
--- a/lib/symboldatabase.cpp
+++ b/lib/symboldatabase.cpp
@@ -3615,26 +3615,50 @@ bool Variable::arrayDimensions(const Settings* settings, bool& isContainer)
return arr;
}
+static std::string scopeTypeToString(Scope::ScopeType type)
+{
+ switch (type) {
+ case Scope::ScopeType::eGlobal:
+ return "Global";
+ case Scope::ScopeType::eClass:
+ return "Class";
+ case Scope::ScopeType::eStruct:
+ return "Struct";
+ case Scope::ScopeType::eUnion:
+ return "Union";
+ case Scope::ScopeType::eNamespace:
+ return "Namespace";
+ case Scope::ScopeType::eFunction:
+ return "Function";
+ case Scope::ScopeType::eIf:
+ return "If";
+ case Scope::ScopeType::eElse:
+ return "Else";
+ case Scope::ScopeType::eFor:
+ return "For";
+ case Scope::ScopeType::eWhile:
+ return "While";
+ case Scope::ScopeType::eDo:
+ return "Do";
+ case Scope::ScopeType::eSwitch:
+ return "Switch";
+ case Scope::ScopeType::eTry:
+ return "Try";
+ case Scope::ScopeType::eCatch:
+ return "Catch";
+ case Scope::ScopeType::eUnconditional:
+ return "Unconditional";
+ case Scope::ScopeType::eLambda:
+ return "Lambda";
+ case Scope::ScopeType::eEnum:
+ return "Enum";
+ }
+ return "Unknown";
+}
+
static std::ostream & operator << (std::ostream & s, Scope::ScopeType type)
{
- s << (type == Scope::eGlobal ? "Global" :
- type == Scope::eClass ? "Class" :
- type == Scope::eStruct ? "Struct" :
- type == Scope::eUnion ? "Union" :
- type == Scope::eNamespace ? "Namespace" :
- type == Scope::eFunction ? "Function" :
- type == Scope::eIf ? "If" :
- type == Scope::eElse ? "Else" :
- type == Scope::eFor ? "For" :
- type == Scope::eWhile ? "While" :
- type == Scope::eDo ? "Do" :
- type == Scope::eSwitch ? "Switch" :
- type == Scope::eTry ? "Try" :
- type == Scope::eCatch ? "Catch" :
- type == Scope::eUnconditional ? "Unconditional" :
- type == Scope::eLambda ? "Lambda" :
- type == Scope::eEnum ? "Enum" :
- "Unknown");
+ s << scopeTypeToString(type);
return s;
}
@@ -4010,137 +4034,223 @@ void SymbolDatabase::printOut(const char *title) const
void SymbolDatabase::printXml(std::ostream &out) const
{
- out << std::setiosflags(std::ios::boolalpha);
+ std::string outs;
std::set variables;
// Scopes..
- out << " " << std::endl;
+ outs += " \n";
for (std::list::const_iterator scope = scopeList.cbegin(); scope != scopeList.cend(); ++scope) {
- out << " type << "\"";
- if (!scope->className.empty())
- out << " className=\"" << ErrorLogger::toxml(scope->className) << "\"";
- if (scope->bodyStart)
- out << " bodyStart=\"" << scope->bodyStart << '\"';
- if (scope->bodyEnd)
- out << " bodyEnd=\"" << scope->bodyEnd << '\"';
- if (scope->nestedIn)
- out << " nestedIn=\"" << scope->nestedIn << "\"";
- if (scope->function)
- out << " function=\"" << scope->function << "\"";
- if (scope->definedType)
- out << " definedType=\"" << scope->definedType << "\"";
+ outs += " type);
+ outs += "\"";
+ if (!scope->className.empty()) {
+ outs += " className=\"";
+ outs += ErrorLogger::toxml(scope->className);
+ outs += "\"";
+ }
+ if (scope->bodyStart) {
+ outs += " bodyStart=\"";
+ outs += id_string(scope->bodyStart);
+ outs += '\"';
+ }
+ if (scope->bodyEnd) {
+ outs += " bodyEnd=\"";
+ outs += id_string(scope->bodyEnd);
+ outs += '\"';
+ }
+ if (scope->nestedIn) {
+ outs += " nestedIn=\"";
+ outs += id_string(scope->nestedIn);
+ outs += "\"";
+ }
+ if (scope->function) {
+ outs += " function=\"";
+ outs += id_string(scope->function);
+ outs += "\"";
+ }
+ if (scope->definedType) {
+ outs += " definedType=\"";
+ outs += id_string(scope->definedType);
+ outs += "\"";
+ }
if (scope->functionList.empty() && scope->varlist.empty())
- out << "/>" << std::endl;
+ outs += "/>\n";
else {
- out << '>' << std::endl;
+ outs += ">\n";
if (!scope->functionList.empty()) {
- out << " " << std::endl;
+ outs += " \n";
for (std::list::const_iterator function = scope->functionList.cbegin(); function != scope->functionList.cend(); ++function) {
- out << " token
- << "\" tokenDef=\"" << function->tokenDef
- << "\" name=\"" << ErrorLogger::toxml(function->name()) << '\"';
- out << " type=\"" << (function->type == Function::eConstructor? "Constructor" :
- function->type == Function::eCopyConstructor ? "CopyConstructor" :
- function->type == Function::eMoveConstructor ? "MoveConstructor" :
- function->type == Function::eOperatorEqual ? "OperatorEqual" :
- function->type == Function::eDestructor ? "Destructor" :
- function->type == Function::eFunction ? "Function" :
- function->type == Function::eLambda ? "Lambda" :
- "Unknown") << '\"';
+ outs += " token);
+ outs += "\" tokenDef=\"";
+ outs += id_string(function->tokenDef);
+ outs += "\" name=\"";
+ outs += ErrorLogger::toxml(function->name());
+ outs += '\"';
+ outs += " type=\"";
+ outs += (function->type == Function::eConstructor? "Constructor" :
+ function->type == Function::eCopyConstructor ? "CopyConstructor" :
+ function->type == Function::eMoveConstructor ? "MoveConstructor" :
+ function->type == Function::eOperatorEqual ? "OperatorEqual" :
+ function->type == Function::eDestructor ? "Destructor" :
+ function->type == Function::eFunction ? "Function" :
+ function->type == Function::eLambda ? "Lambda" :
+ "Unknown");
+ outs += '\"';
if (function->nestedIn->definedType) {
if (function->hasVirtualSpecifier())
- out << " hasVirtualSpecifier=\"true\"";
+ outs += " hasVirtualSpecifier=\"true\"";
else if (function->isImplicitlyVirtual())
- out << " isImplicitlyVirtual=\"true\"";
+ outs += " isImplicitlyVirtual=\"true\"";
+ }
+ if (function->access == AccessControl::Public || function->access == AccessControl::Protected || function->access == AccessControl::Private) {
+ outs += " access=\"";
+ outs += accessControlToString(function->access);
+ outs +="\"";
}
- if (function->access == AccessControl::Public || function->access == AccessControl::Protected || function->access == AccessControl::Private)
- out << " access=\"" << accessControlToString(function->access) << "\"";
if (function->isInlineKeyword())
- out << " isInlineKeyword=\"true\"";
+ outs += " isInlineKeyword=\"true\"";
if (function->isStatic())
- out << " isStatic=\"true\"";
+ outs += " isStatic=\"true\"";
if (function->isAttributeNoreturn())
- out << " isAttributeNoreturn=\"true\"";
- if (const Function* overriddenFunction = function->getOverriddenFunction())
- out << " overriddenFunction=\"" << overriddenFunction << "\"";
+ outs += " isAttributeNoreturn=\"true\"";
+ if (const Function* overriddenFunction = function->getOverriddenFunction()) {
+ outs += " overriddenFunction=\"";
+ outs += id_string(overriddenFunction);
+ outs += "\"";
+ }
if (function->argCount() == 0U)
- out << "/>" << std::endl;
+ outs += "/>\n";
else {
- out << ">" << std::endl;
+ outs += ">\n";
for (unsigned int argnr = 0; argnr < function->argCount(); ++argnr) {
const Variable *arg = function->getArgumentVar(argnr);
- out << " " << std::endl;
+ outs += " \n";
variables.insert(arg);
}
- out << " " << std::endl;
+ outs += " \n";
}
}
- out << " " << std::endl;
+ outs += " \n";
}
if (!scope->varlist.empty()) {
- out << " " << std::endl;
- for (std::list::const_iterator var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var)
- out << " " << std::endl;
- out << " " << std::endl;
+ outs += " \n";
+ for (std::list::const_iterator var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var) {
+ outs += " \n";
+ }
+ outs += " \n";
}
- out << " " << std::endl;
+ outs += " \n";
}
}
- out << " " << std::endl;
+ outs += " \n";
if (!typeList.empty()) {
- out << " \n";
+ outs += " \n";
for (const Type& type:typeList) {
- out << " \n";
+ outs += "/>\n";
continue;
}
- out << ">\n";
+ outs += ">\n";
for (const Type::BaseInfo& baseInfo: type.derivedFrom) {
- out << " \n";
- }
- out << " \n";
- }
- out << " \n";
+ outs += " \n";
+ }
+ outs += " \n";
+ }
+ outs += " \n";
}
// Variables..
for (const Variable *var : mVariableList)
variables.insert(var);
- out << " " << std::endl;
+ outs += " \n";
for (const Variable *var : variables) {
if (!var)
continue;
- out << " nameToken() << '\"';
- out << " typeStartToken=\"" << var->typeStartToken() << '\"';
- out << " typeEndToken=\"" << var->typeEndToken() << '\"';
- out << " access=\"" << accessControlToString(var->mAccess) << '\"';
- out << " scope=\"" << var->scope() << '\"';
- if (var->valueType())
- out << " constness=\"" << var->valueType()->constness << '\"';
- out << " isArray=\"" << var->isArray() << '\"';
- out << " isClass=\"" << var->isClass() << '\"';
- out << " isConst=\"" << var->isConst() << '\"';
- out << " isExtern=\"" << var->isExtern() << '\"';
- out << " isPointer=\"" << var->isPointer() << '\"';
- out << " isReference=\"" << var->isReference() << '\"';
- out << " isStatic=\"" << var->isStatic() << '\"';
- out << " isVolatile=\"" << var->isVolatile() << '\"';
- out << "/>" << std::endl;
- }
- out << " " << std::endl;
- out << std::resetiosflags(std::ios::boolalpha);
+ outs += " nameToken());
+ outs += '\"';
+ outs += " typeStartToken=\"";
+ outs += id_string(var->typeStartToken());
+ outs += '\"';
+ outs += " typeEndToken=\"";
+ outs += id_string(var->typeEndToken());
+ outs += '\"';
+ outs += " access=\"";
+ outs += accessControlToString(var->mAccess);
+ outs += '\"';
+ outs += " scope=\"";
+ outs += id_string(var->scope());
+ outs += '\"';
+ if (var->valueType()) {
+ outs += " constness=\"";
+ outs += std::to_string(var->valueType()->constness);
+ outs += '\"';
+ }
+ outs += " isArray=\"";
+ outs += bool_to_string(var->isArray());
+ outs += '\"';
+ outs += " isClass=\"";
+ outs += bool_to_string(var->isClass());
+ outs += '\"';
+ outs += " isConst=\"";
+ outs += bool_to_string(var->isConst());
+ outs += '\"';
+ outs += " isExtern=\"";
+ outs += bool_to_string(var->isExtern());
+ outs += '\"';
+ outs += " isPointer=\"";
+ outs += bool_to_string(var->isPointer());
+ outs += '\"';
+ outs += " isReference=\"";
+ outs += bool_to_string(var->isReference());
+ outs += '\"';
+ outs += " isStatic=\"";
+ outs += bool_to_string(var->isStatic());
+ outs += '\"';
+ outs += " isVolatile=\"";
+ outs += bool_to_string(var->isVolatile());
+ outs += '\"';
+ outs += "/>\n";
+ }
+ outs += " \n";
+
+ out << outs;
}
//---------------------------------------------------------------------------
@@ -5357,7 +5467,7 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
addMatchingFunctions(this);
- // check in anonumous namespaces
+ // check in anonymous namespaces
for (const Scope *nestedScope : nestedList) {
if (nestedScope->type == eNamespace && nestedScope->className.empty())
addMatchingFunctions(nestedScope);
@@ -5577,6 +5687,25 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
if (matches.size() == 1)
return matches[0];
+ // Prioritize matches in derived scopes
+ for (const auto& fb : { fallback1Func, fallback2Func }) {
+ const Function* ret = nullptr;
+ for (int i = 0; i < fb.size(); ++i) {
+ if (std::find(matches.cbegin(), matches.cend(), fb[i]) == matches.cend())
+ continue;
+ if (this == fb[i]->nestedIn) {
+ if (!ret)
+ ret = fb[i];
+ else {
+ ret = nullptr;
+ break;
+ }
+ }
+ }
+ if (ret)
+ return ret;
+ }
+
return nullptr;
}
@@ -7443,64 +7572,67 @@ bool ValueType::fromLibraryType(const std::string &typestr, const Settings &sett
std::string ValueType::dump() const
{
- std::ostringstream ret;
+ std::string ret;
switch (type) {
case UNKNOWN_TYPE:
return "";
case NONSTD:
- ret << "valueType-type=\"nonstd\"";
+ ret += "valueType-type=\"nonstd\"";
break;
case POD:
- ret << "valueType-type=\"pod\"";
+ ret += "valueType-type=\"pod\"";
break;
case RECORD:
- ret << "valueType-type=\"record\"";
+ ret += "valueType-type=\"record\"";
break;
case SMART_POINTER:
- ret << "valueType-type=\"smart-pointer\"";
+ ret += "valueType-type=\"smart-pointer\"";
break;
- case CONTAINER:
- ret << "valueType-type=\"container\"";
- ret << " valueType-containerId=\"" << container << "\"";
+ case CONTAINER: {
+ ret += "valueType-type=\"container\"";
+ ret += " valueType-containerId=\"";
+ ret += id_string(container);
+ ret += "\"";
break;
+ }
case ITERATOR:
- ret << "valueType-type=\"iterator\"";
+ ret += "valueType-type=\"iterator\"";
break;
case VOID:
- ret << "valueType-type=\"void\"";
+ ret += "valueType-type=\"void\"";
break;
case BOOL:
- ret << "valueType-type=\"bool\"";
+ ret += "valueType-type=\"bool\"";
break;
case CHAR:
- ret << "valueType-type=\"char\"";
+ ret += "valueType-type=\"char\"";
break;
case SHORT:
- ret << "valueType-type=\"short\"";
+ ret += "valueType-type=\"short\"";
break;
case WCHAR_T:
- ret << "valueType-type=\"wchar_t\"";
+ ret += "valueType-type=\"wchar_t\"";
break;
case INT:
- ret << "valueType-type=\"int\"";
+ ret += "valueType-type=\"int\"";
break;
case LONG:
- ret << "valueType-type=\"long\"";
+ ret += "valueType-type=\"long\"";
break;
case LONGLONG:
- ret << "valueType-type=\"long long\"";
+ ret += "valueType-type=\"long long\"";
break;
case UNKNOWN_INT:
- ret << "valueType-type=\"unknown int\"";
+ ret += "valueType-type=\"unknown int\"";
break;
case FLOAT:
- ret << "valueType-type=\"float\"";
+ ret += "valueType-type=\"float\"";
break;
case DOUBLE:
- ret << "valueType-type=\"double\"";
+ ret += "valueType-type=\"double\"";
break;
case LONGDOUBLE:
- ret << "valueType-type=\"long double\"";
+ ret += "valueType-type=\"long double\"";
break;
}
@@ -7508,36 +7640,51 @@ std::string ValueType::dump() const
case Sign::UNKNOWN_SIGN:
break;
case Sign::SIGNED:
- ret << " valueType-sign=\"signed\"";
+ ret += " valueType-sign=\"signed\"";
break;
case Sign::UNSIGNED:
- ret << " valueType-sign=\"unsigned\"";
+ ret += " valueType-sign=\"unsigned\"";
break;
}
- if (bits > 0)
- ret << " valueType-bits=\"" << bits << '\"';
+ if (bits > 0) {
+ ret += " valueType-bits=\"";
+ ret += std::to_string(bits);
+ ret += '\"';
+ }
- if (pointer > 0)
- ret << " valueType-pointer=\"" << pointer << '\"';
+ if (pointer > 0) {
+ ret += " valueType-pointer=\"";
+ ret += std::to_string(pointer);
+ ret += '\"';
+ }
- if (constness > 0)
- ret << " valueType-constness=\"" << constness << '\"';
+ if (constness > 0) {
+ ret += " valueType-constness=\"";
+ ret += std::to_string(constness);
+ ret += '\"';
+ }
if (reference == Reference::None)
- ret << " valueType-reference=\"None\"";
+ ret += " valueType-reference=\"None\"";
else if (reference == Reference::LValue)
- ret << " valueType-reference=\"LValue\"";
+ ret += " valueType-reference=\"LValue\"";
else if (reference == Reference::RValue)
- ret << " valueType-reference=\"RValue\"";
+ ret += " valueType-reference=\"RValue\"";
- if (typeScope)
- ret << " valueType-typeScope=\"" << typeScope << '\"';
+ if (typeScope) {
+ ret += " valueType-typeScope=\"";
+ ret += id_string(typeScope);
+ ret += '\"';
+ }
- if (!originalTypeName.empty())
- ret << " valueType-originalTypeName=\"" << ErrorLogger::toxml(originalTypeName) << '\"';
+ if (!originalTypeName.empty()) {
+ ret += " valueType-originalTypeName=\"";
+ ret += ErrorLogger::toxml(originalTypeName);
+ ret += '\"';
+ }
- return ret.str();
+ return ret;
}
bool ValueType::isConst(nonneg int indirect) const
diff --git a/lib/token.cpp b/lib/token.cpp
index a13f98763d4..0ad96387d61 100644
--- a/lib/token.cpp
+++ b/lib/token.cpp
@@ -1695,119 +1695,171 @@ std::string Token::astStringZ3() const
void Token::printValueFlow(bool xml, std::ostream &out) const
{
+ std::string outs;
+
int line = 0;
if (xml)
- out << " " << std::endl;
+ outs += " \n";
else
- out << "\n\n##Value flow" << std::endl;
+ outs += "\n\n##Value flow\n";
for (const Token *tok = this; tok; tok = tok->next()) {
const auto* const values = tok->mImpl->mValues;
if (!values)
continue;
if (values->empty()) // Values might be removed by removeContradictions
continue;
- if (xml)
- out << " " << std::endl;
- else if (line != tok->linenr())
- out << "Line " << tok->linenr() << std::endl;
+ if (xml) {
+ outs += " ";
+ outs += '\n';
+ }
+ else if (line != tok->linenr()) {
+ outs += "Line ";
+ outs += std::to_string(tok->linenr());
+ outs += '\n';
+ }
line = tok->linenr();
if (!xml) {
ValueFlow::Value::ValueKind valueKind = values->front().valueKind;
const bool same = std::all_of(values->begin(), values->end(), [&](const ValueFlow::Value& value) {
return value.valueKind == valueKind;
});
- out << " " << tok->str() << " ";
+ outs += " ";
+ outs += tok->str();
+ outs += " ";
if (same) {
switch (valueKind) {
case ValueFlow::Value::ValueKind::Impossible:
case ValueFlow::Value::ValueKind::Known:
- out << "always ";
+ outs += "always ";
break;
case ValueFlow::Value::ValueKind::Inconclusive:
- out << "inconclusive ";
+ outs += "inconclusive ";
break;
case ValueFlow::Value::ValueKind::Possible:
- out << "possible ";
+ outs += "possible ";
break;
}
}
if (values->size() > 1U)
- out << '{';
+ outs += '{';
}
for (const ValueFlow::Value& value : *values) {
if (xml) {
- out << " valueType() && tok->valueType()->sign == ValueType::UNSIGNED)
- out << "intvalue=\"" << (MathLib::biguint)value.intvalue << '\"';
- else
- out << "intvalue=\"" << value.intvalue << '\"';
+ if (tok->valueType() && tok->valueType()->sign == ValueType::UNSIGNED) {
+ outs += "intvalue=\"";
+ outs += std::to_string(static_cast(value.intvalue));
+ outs += '\"';
+ }
+ else {
+ outs += "intvalue=\"";
+ outs += std::to_string(value.intvalue);
+ outs += '\"';
+ }
break;
case ValueFlow::Value::ValueType::TOK:
- out << "tokvalue=\"" << value.tokvalue << '\"';
+ outs += "tokvalue=\"";
+ outs += id_string(value.tokvalue);
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::FLOAT:
- out << "floatvalue=\"" << value.floatValue << '\"';
+ outs += "floatvalue=\"";
+ outs += std::to_string(value.floatValue); // TODO: should this be MathLib::toString()?
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::MOVED:
- out << "movedvalue=\"" << ValueFlow::Value::toString(value.moveKind) << '\"';
+ outs += "movedvalue=\"";
+ outs += ValueFlow::Value::toString(value.moveKind);
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::UNINIT:
- out << "uninit=\"1\"";
+ outs += "uninit=\"1\"";
break;
case ValueFlow::Value::ValueType::BUFFER_SIZE:
- out << "buffer-size=\"" << value.intvalue << "\"";
+ outs += "buffer-size=\"";
+ outs += std::to_string(value.intvalue);
+ outs += "\"";
break;
case ValueFlow::Value::ValueType::CONTAINER_SIZE:
- out << "container-size=\"" << value.intvalue << '\"';
+ outs += "container-size=\"";
+ outs += std::to_string(value.intvalue);
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::ITERATOR_START:
- out << "iterator-start=\"" << value.intvalue << '\"';
+ outs += "iterator-start=\"";
+ outs += std::to_string(value.intvalue);
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::ITERATOR_END:
- out << "iterator-end=\"" << value.intvalue << '\"';
+ outs += "iterator-end=\"";
+ outs += std::to_string(value.intvalue);
+ outs += '\"';
break;
case ValueFlow::Value::ValueType::LIFETIME:
- out << "lifetime=\"" << value.tokvalue << '\"';
- out << " lifetime-scope=\"" << ValueFlow::Value::toString(value.lifetimeScope) << "\"";
- out << " lifetime-kind=\"" << ValueFlow::Value::toString(value.lifetimeKind) << "\"";
+ outs += "lifetime=\"";
+ outs += id_string(value.tokvalue);
+ outs += '\"';
+ outs += " lifetime-scope=\"";
+ outs += ValueFlow::Value::toString(value.lifetimeScope);
+ outs += "\"";
+ outs += " lifetime-kind=\"";
+ outs += ValueFlow::Value::toString(value.lifetimeKind);
+ outs += "\"";
break;
case ValueFlow::Value::ValueType::SYMBOLIC:
- out << "symbolic=\"" << value.tokvalue << '\"';
- out << " symbolic-delta=\"" << value.intvalue << '\"';
+ outs += "symbolic=\"";
+ outs += id_string(value.tokvalue);
+ outs += '\"';
+ outs += " symbolic-delta=\"";
+ outs += std::to_string(value.intvalue);
+ outs += '\"';
break;
}
- out << " bound=\"" << ValueFlow::Value::toString(value.bound) << "\"";
- if (value.condition)
- out << " condition-line=\"" << value.condition->linenr() << '\"';
+ outs += " bound=\"";
+ outs += ValueFlow::Value::toString(value.bound);
+ outs += "\"";
+ if (value.condition) {
+ outs += " condition-line=\"";
+ outs += std::to_string(value.condition->linenr());
+ outs += '\"';
+ }
if (value.isKnown())
- out << " known=\"true\"";
+ outs += " known=\"true\"";
else if (value.isPossible())
- out << " possible=\"true\"";
+ outs += " possible=\"true\"";
else if (value.isImpossible())
- out << " impossible=\"true\"";
+ outs += " impossible=\"true\"";
else if (value.isInconclusive())
- out << " inconclusive=\"true\"";
- out << " path=\"" << value.path << "\"";
- out << "/>" << std::endl;
+ outs += " inconclusive=\"true\"";
+
+ outs += " path=\"";
+ outs += std::to_string(value.path);
+ outs += "\"";
+
+ outs += "/>\n";
}
else {
if (&value != &values->front())
- out << ",";
- out << value.toString();
+ outs += ",";
+ outs += value.toString();
}
}
if (xml)
- out << " " << std::endl;
+ outs += " \n";
else if (values->size() > 1U)
- out << '}' << std::endl;
+ outs += "}\n";
else
- out << std::endl;
+ outs += '\n';
}
if (xml)
- out << " " << std::endl;
+ outs += " \n";
+
+ out << outs;
}
const ValueFlow::Value * Token::getValueLE(const MathLib::bigint val, const Settings *settings) const
diff --git a/lib/token.h b/lib/token.h
index dfd601a7677..e50fbec9ac6 100644
--- a/lib/token.h
+++ b/lib/token.h
@@ -684,6 +684,13 @@ class CPPCHECKLIB Token {
setFlag(fIsFinalType, b);
}
+ bool isInitComma() const {
+ return getFlag(fIsInitComma);
+ }
+ void isInitComma(bool b) {
+ setFlag(fIsInitComma, b);
+ }
+
bool isBitfield() const {
return mImpl->mBits > 0;
}
@@ -1307,14 +1314,14 @@ class CPPCHECKLIB Token {
fIsAttributePacked = (1ULL << 15), // __attribute__((packed))
fIsAttributeExport = (1ULL << 16), // __attribute__((__visibility__("default"))), __declspec(dllexport)
fIsAttributeMaybeUnused = (1ULL << 17), // [[maybe_unsed]]
- fIsControlFlowKeyword = (1ULL << 18), // if/switch/while/...
- fIsOperatorKeyword = (1ULL << 19), // operator=, etc
- fIsComplex = (1ULL << 20), // complex/_Complex type
- fIsEnumType = (1ULL << 21), // enumeration type
- fIsName = (1ULL << 22),
- fIsLiteral = (1ULL << 23),
- fIsTemplateArg = (1ULL << 24),
- fIsAttributeNodiscard = (1ULL << 25), // __attribute__ ((warn_unused_result)), [[nodiscard]]
+ fIsAttributeNodiscard = (1ULL << 18), // __attribute__ ((warn_unused_result)), [[nodiscard]]
+ fIsControlFlowKeyword = (1ULL << 19), // if/switch/while/...
+ fIsOperatorKeyword = (1ULL << 20), // operator=, etc
+ fIsComplex = (1ULL << 21), // complex/_Complex type
+ fIsEnumType = (1ULL << 22), // enumeration type
+ fIsName = (1ULL << 23),
+ fIsLiteral = (1ULL << 24),
+ fIsTemplateArg = (1ULL << 25),
fAtAddress = (1ULL << 26), // @ 0x4000
fIncompleteVar = (1ULL << 27),
fConstexpr = (1ULL << 28),
@@ -1331,6 +1338,7 @@ class CPPCHECKLIB Token {
fIsAtomic = (1ULL << 39), // Is this a _Atomic declaration
fIsSimplifiedTypedef = (1ULL << 40),
fIsFinalType = (1ULL << 41), // Is this a type with final specifier
+ fIsInitComma = (1ULL << 42), // Is this comma located inside some {..}. i.e: {1,2,3,4}
};
enum : uint64_t {
diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp
index 86a843c9632..cc4f3cfa015 100644
--- a/lib/tokenize.cpp
+++ b/lib/tokenize.cpp
@@ -4014,8 +4014,8 @@ void Tokenizer::simplifyTemplates()
/** Class used in Tokenizer::setVarIdPass1 */
class VariableMap {
private:
- std::map mVariableId;
- std::map mVariableId_global;
+ std::unordered_map mVariableId;
+ std::unordered_map mVariableId_global;
std::stack>> mScopeInfo;
mutable nonneg int mVarId{};
public:
@@ -4027,7 +4027,7 @@ class VariableMap {
return mVariableId.find(varname) != mVariableId.end();
}
- const std::map& map(bool global) const {
+ const std::unordered_map& map(bool global) const {
return global ? mVariableId_global : mVariableId;
}
nonneg int getVarId() const {
@@ -4067,7 +4067,7 @@ void VariableMap::addVariable(const std::string& varname, bool globalNamespace)
mVariableId_global[varname] = mVariableId[varname];
return;
}
- std::map::iterator it = mVariableId.find(varname);
+ std::unordered_map::iterator it = mVariableId.find(varname);
if (it == mVariableId.end()) {
mScopeInfo.top().emplace_back(varname, 0);
mVariableId[varname] = ++mVarId;
@@ -4330,7 +4330,7 @@ void Tokenizer::setVarIdClassDeclaration(Token* const startToken,
--indentlevel;
inEnum = false;
} else if (initList && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %name% [({]")) {
- const std::map::const_iterator it = variableMap.map(false).find(tok->str());
+ const std::unordered_map::const_iterator it = variableMap.map(false).find(tok->str());
if (it != variableMap.map(false).end()) {
tok->varId(it->second);
}
@@ -4348,7 +4348,7 @@ void Tokenizer::setVarIdClassDeclaration(Token* const startToken,
}
if (!inEnum) {
- const std::map::const_iterator it = variableMap.map(false).find(tok->str());
+ const std::unordered_map::const_iterator it = variableMap.map(false).find(tok->str());
if (it != variableMap.map(false).end()) {
tok->varId(it->second);
setVarIdStructMembers(&tok, structMembers, variableMap.getVarId());
@@ -4692,7 +4692,7 @@ void Tokenizer::setVarIdPass1()
while (tok != end) {
if (tok->isName() && !(Token::simpleMatch(tok->next(), "<") &&
Token::Match(tok->tokAt(-1), ":: %name%"))) {
- const std::map::const_iterator it = variableMap.map(false).find(tok->str());
+ const std::unordered_map::const_iterator it = variableMap.map(false).find(tok->str());
if (it != variableMap.map(false).end())
tok->varId(it->second);
}
@@ -4757,7 +4757,7 @@ void Tokenizer::setVarIdPass1()
if ((!scopeStack.top().isEnum || !(Token::Match(tok->previous(), "{|,") && Token::Match(tok->next(), ",|=|}"))) &&
!Token::simpleMatch(tok->next(), ": ;")) {
- const std::map::const_iterator it = variableMap.map(globalNamespace).find(tok->str());
+ const std::unordered_map::const_iterator it = variableMap.map(globalNamespace).find(tok->str());
if (it != variableMap.map(globalNamespace).end()) {
tok->varId(it->second);
setVarIdStructMembers(&tok, structMembers, variableMap.getVarId());
@@ -5797,134 +5797,223 @@ void Tokenizer::dump(std::ostream &out) const
// The idea is not that this will be readable for humans. It's a
// data dump that 3rd party tools could load and get useful info from.
+ std::string outs;
+
std::set containers;
// tokens..
- out << " " << std::endl;
+ outs += " ";
+ outs += '\n';
for (const Token *tok = list.front(); tok; tok = tok->next()) {
- out << " linenr() << "\" column=\"" << tok->column() << "\"";
- out << " str=\"" << ErrorLogger::toxml(tok->str()) << '\"';
- out << " scope=\"" << tok->scope() << '\"';
+ outs += " linenr());
+ outs += "\" column=\"";
+ outs += std::to_string(tok->column());
+ outs += "\"";
+
+ outs += " str=\"";
+ outs += ErrorLogger::toxml(tok->str());
+ outs += '\"';
+
+ outs += " scope=\"";
+ outs += id_string(tok->scope());
+ outs += '\"';
if (tok->isName()) {
- out << " type=\"name\"";
+ outs += " type=\"name\"";
if (tok->isUnsigned())
- out << " isUnsigned=\"true\"";
+ outs += " isUnsigned=\"true\"";
else if (tok->isSigned())
- out << " isSigned=\"true\"";
+ outs += " isSigned=\"true\"";
} else if (tok->isNumber()) {
- out << " type=\"number\"";
+ outs += " type=\"number\"";
if (MathLib::isInt(tok->str()))
- out << " isInt=\"true\"";
+ outs += " isInt=\"true\"";
if (MathLib::isFloat(tok->str()))
- out << " isFloat=\"true\"";
- } else if (tok->tokType() == Token::eString)
- out << " type=\"string\" strlen=\"" << Token::getStrLength(tok) << '\"';
+ outs += " isFloat=\"true\"";
+ } else if (tok->tokType() == Token::eString) {
+ outs += " type=\"string\" strlen=\"";
+ outs += std::to_string(Token::getStrLength(tok));
+ outs += '\"';
+ }
else if (tok->tokType() == Token::eChar)
- out << " type=\"char\"";
+ outs += " type=\"char\"";
else if (tok->isBoolean())
- out << " type=\"boolean\"";
+ outs += " type=\"boolean\"";
else if (tok->isOp()) {
- out << " type=\"op\"";
+ outs += " type=\"op\"";
if (tok->isArithmeticalOp())
- out << " isArithmeticalOp=\"true\"";
+ outs += " isArithmeticalOp=\"true\"";
else if (tok->isAssignmentOp())
- out << " isAssignmentOp=\"true\"";
+ outs += " isAssignmentOp=\"true\"";
else if (tok->isComparisonOp())
- out << " isComparisonOp=\"true\"";
+ outs += " isComparisonOp=\"true\"";
else if (tok->tokType() == Token::eLogicalOp)
- out << " isLogicalOp=\"true\"";
+ outs += " isLogicalOp=\"true\"";
}
if (tok->isCast())
- out << " isCast=\"true\"";
+ outs += " isCast=\"true\"";
if (tok->isExternC())
- out << " externLang=\"C\"";
+ outs += " externLang=\"C\"";
if (tok->isExpandedMacro())
- out << " isExpandedMacro=\"true\"";
+ outs += " isExpandedMacro=\"true\"";
if (tok->isTemplateArg())
- out << " isTemplateArg=\"true\"";
+ outs += " isTemplateArg=\"true\"";
if (tok->isRemovedVoidParameter())
- out << " isRemovedVoidParameter=\"true\"";
+ outs += " isRemovedVoidParameter=\"true\"";
if (tok->isSplittedVarDeclComma())
- out << " isSplittedVarDeclComma=\"true\"";
+ outs += " isSplittedVarDeclComma=\"true\"";
if (tok->isSplittedVarDeclEq())
- out << " isSplittedVarDeclEq=\"true\"";
+ outs += " isSplittedVarDeclEq=\"true\"";
if (tok->isImplicitInt())
- out << " isImplicitInt=\"true\"";
+ outs += " isImplicitInt=\"true\"";
if (tok->isComplex())
- out << " isComplex=\"true\"";
+ outs += " isComplex=\"true\"";
if (tok->isRestrict())
- out << " isRestrict=\"true\"";
+ outs += " isRestrict=\"true\"";
if (tok->isAtomic())
- out << " isAtomic=\"true\"";
+ outs += " isAtomic=\"true\"";
if (tok->isAttributeExport())
- out << " isAttributeExport=\"true\"";
- if (tok->link())
- out << " link=\"" << tok->link() << '\"';
- if (tok->varId() > 0)
- out << " varId=\"" << tok->varId() << '\"';
- if (tok->exprId() > 0)
- out << " exprId=\"" << tok->exprId() << '\"';
- if (tok->variable())
- out << " variable=\"" << tok->variable() << '\"';
- if (tok->function())
- out << " function=\"" << tok->function() << '\"';
- if (!tok->values().empty())
- out << " values=\"" << &tok->values() << '\"';
- if (tok->type())
- out << " type-scope=\"" << tok->type()->classScope << '\"';
- if (tok->astParent())
- out << " astParent=\"" << tok->astParent() << '\"';
- if (tok->astOperand1())
- out << " astOperand1=\"" << tok->astOperand1() << '\"';
- if (tok->astOperand2())
- out << " astOperand2=\"" << tok->astOperand2() << '\"';
- if (!tok->originalName().empty())
- out << " originalName=\"" << tok->originalName() << '\"';
+ outs += " isAttributeExport=\"true\"";
+ if (tok->link()) {
+ outs += " link=\"";
+ outs += id_string(tok->link());
+ outs += '\"';
+ }
+ if (tok->varId() > 0) {
+ outs += " varId=\"";
+ outs += std::to_string(tok->varId());
+ outs += '\"';
+ }
+ if (tok->exprId() > 0) {
+ outs += " exprId=\"";
+ outs += std::to_string(tok->exprId());
+ outs += '\"';
+ }
+ if (tok->variable()) {
+ outs += " variable=\"";
+ outs += id_string(tok->variable());
+ outs += '\"';
+ }
+ if (tok->function()) {
+ outs += " function=\"";
+ outs += id_string(tok->function());
+ outs += '\"';
+ }
+ if (!tok->values().empty()) {
+ outs += " values=\"";
+ outs += id_string(&tok->values());
+ outs += '\"';
+ }
+ if (tok->type()) {
+ outs += " type-scope=\"";
+ outs += id_string(tok->type()->classScope);
+ outs += '\"';
+ }
+ if (tok->astParent()) {
+ outs += " astParent=\"";
+ outs += id_string(tok->astParent());
+ outs += '\"';
+ }
+ if (tok->astOperand1()) {
+ outs += " astOperand1=\"";
+ outs += id_string(tok->astOperand1());
+ outs += '\"';
+ }
+ if (tok->astOperand2()) {
+ outs += " astOperand2=\"";
+ outs += id_string(tok->astOperand2());
+ outs += '\"';
+ }
+ if (!tok->originalName().empty()) {
+ outs += " originalName=\"";
+ outs += tok->originalName();
+ outs += '\"';
+ }
if (tok->valueType()) {
const std::string vt = tok->valueType()->dump();
- if (!vt.empty())
- out << ' ' << vt;
+ if (!vt.empty()) {
+ outs += ' ';
+ outs += vt;
+ }
containers.insert(tok->valueType()->container);
}
if (!tok->varId() && tok->scope()->isExecutable() && Token::Match(tok, "%name% (")) {
if (mSettings->library.isnoreturn(tok))
- out << " noreturn=\"true\"";
+ outs += " noreturn=\"true\"";
}
- out << "/>" << std::endl;
+ outs += "/>";
+ outs += '\n';
}
- out << " " << std::endl;
+ outs += " ";
+ outs += '\n';
+
+ out << outs;
+ outs.clear();
mSymbolDatabase->printXml(out);
containers.erase(nullptr);
if (!containers.empty()) {
- out << " \n";
+ outs += " ";
+ outs += '\n';
for (const Library::Container* c: containers) {
- out << " arrayLike_indexOp ? "true" : "false") << "\" "
- << "std-string-like=\"" << (c->stdStringLike ? "true" : "false") << "\"/>\n";
+ outs += " arrayLike_indexOp ? "true" : "false");
+ outs += "\" ";
+ outs += "std-string-like=\"";
+ outs +=(c->stdStringLike ? "true" : "false");
+ outs += "\"/>";
+ outs += '\n';
}
- out << " \n";
+ outs += " ";
+ outs += '\n';
}
if (list.front())
list.front()->printValueFlow(true, out);
if (!mTypedefInfo.empty()) {
- out << " " << std::endl;
+ outs += " ";
+ outs += '\n';
for (const TypedefInfo &typedefInfo: mTypedefInfo) {
- out << " " << std::endl;
+ outs += " ";
+ outs += '\n';
}
- out << " " << std::endl;
+ outs += " ";
+ outs += '\n';
}
- out << mTemplateSimplifier->dump();
+ outs += mTemplateSimplifier->dump();
+
+ out << outs;
}
void Tokenizer::simplifyHeadersAndUnusedTemplates()
diff --git a/lib/utils.h b/lib/utils.h
index e942c82f1da..46ee7d69861 100644
--- a/lib/utils.h
+++ b/lib/utils.h
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -269,4 +270,53 @@ std::size_t getArrayLength(const T (& /*unused*/)[size])
return size;
}
+/**
+ * @brief get id string. i.e. for dump files
+ * it will be a hexadecimal output.
+ */
+static inline std::string id_string_i(std::uintptr_t l)
+{
+ if (!l)
+ return "0";
+
+ static constexpr int ptr_size = sizeof(void*);
+
+ // two characters of each byte / contains terminating \0
+ static constexpr int buf_size = (ptr_size * 2) + 1;
+
+ char buf[buf_size];
+
+ // needs to be signed so we don't underflow in padding loop
+ int idx = buf_size - 1;
+ buf[idx] = '\0';
+
+ while (l != 0)
+ {
+ char c;
+ const uintptr_t temp = l % 16; // get the remainder
+ if (temp < 10) {
+ // 0-9
+ c = '0' + temp;
+ }
+ else {
+ // a-f
+ c = 'a' + (temp - 10);
+ }
+ buf[--idx] = c; // store in reverse order
+ l = l / 16;
+ }
+
+ return &buf[idx];
+}
+
+static inline std::string id_string(const void* p)
+{
+ return id_string_i(reinterpret_cast(p));
+}
+
+static inline std::string bool_to_string(bool b)
+{
+ return b ? "true" : "false";
+}
+
#endif
diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp
index b97389fe9bb..396879b90d4 100644
--- a/lib/valueflow.cpp
+++ b/lib/valueflow.cpp
@@ -605,7 +605,6 @@ static ValueFlow::Value truncateImplicitConversion(Token* parent, const ValueFlo
static void setTokenValue(Token* tok,
ValueFlow::Value value,
const Settings* settings,
- bool isInitList = false,
SourceLocation loc = SourceLocation::current())
{
// Skip setting values that are too big since its ambiguous
@@ -629,7 +628,7 @@ static void setTokenValue(Token* tok,
if (!parent)
return;
- if (!isInitList && Token::simpleMatch(parent, ",") && astIsRHS(tok)) {
+ if (Token::simpleMatch(parent, ",") && !parent->isInitComma() && astIsRHS(tok)) {
const Token* callParent = findParent(parent, [](const Token* p) {
return !Token::simpleMatch(p, ",");
});
@@ -947,7 +946,7 @@ static void setTokenValue(Token* tok,
if (Token::simpleMatch(parent, "-") && value2.bound == result.bound &&
value2.bound != ValueFlow::Value::Bound::Point)
result.invertBound();
- setTokenValue(parent, result, settings, isInitList);
+ setTokenValue(parent, result, settings);
}
}
}
@@ -1131,7 +1130,7 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings *settings)
static bool getMinMaxValues(const ValueType* vt, const cppcheck::Platform& platform, MathLib::bigint& minValue, MathLib::bigint& maxValue);
// Handle various constants..
-static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, bool cpp, bool isInitList = false)
+static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, bool cpp)
{
if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) {
try {
@@ -1145,7 +1144,7 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b
ValueFlow::Value value(signedValue);
if (!tok->isTemplateArg())
value.setKnown();
- setTokenValue(tok, std::move(value), settings, isInitList);
+ setTokenValue(tok, std::move(value), settings);
} catch (const std::exception & /*e*/) {
// Bad character literal
}
@@ -1155,17 +1154,17 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b
value.floatValue = MathLib::toDoubleNumber(tok->str());
if (!tok->isTemplateArg())
value.setKnown();
- setTokenValue(tok, std::move(value), settings, isInitList);
+ setTokenValue(tok, std::move(value), settings);
} else if (tok->enumerator() && tok->enumerator()->value_known) {
ValueFlow::Value value(tok->enumerator()->value);
if (!tok->isTemplateArg())
value.setKnown();
- setTokenValue(tok, std::move(value), settings, isInitList);
+ setTokenValue(tok, std::move(value), settings);
} else if (tok->str() == "NULL" || (cpp && tok->str() == "nullptr")) {
ValueFlow::Value value(0);
if (!tok->isTemplateArg())
value.setKnown();
- setTokenValue(tok, std::move(value), settings, isInitList);
+ setTokenValue(tok, std::move(value), settings);
} else if (Token::simpleMatch(tok, "sizeof (")) {
if (tok->next()->astOperand2() && !tok->next()->astOperand2()->isLiteral() && tok->next()->astOperand2()->valueType() &&
(tok->next()->astOperand2()->valueType()->pointer == 0 || // <- TODO this is a bailout, abort when there are array->pointer conversions
@@ -1333,17 +1332,17 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b
ValueFlow::Value value(0);
if (!tok->isTemplateArg())
value.setKnown();
- setTokenValue(tok->next(), std::move(value), settings, isInitList);
+ setTokenValue(tok->next(), std::move(value), settings);
} else if (Token::Match(tok, "%name% = {") && tok->variable() &&
(tok->variable()->isPointer() || (tok->variable()->valueType() && tok->variable()->valueType()->isIntegral()))) {
if (Token::simpleMatch(tok->tokAt(3), "}")) {
ValueFlow::Value value(0);
value.setKnown();
- setTokenValue(tok->tokAt(2), std::move(value), settings, isInitList);
+ setTokenValue(tok->tokAt(2), std::move(value), settings);
} else if (tok->tokAt(2)->astOperand1() && tok->tokAt(2)->astOperand1()->hasKnownIntValue()) {
ValueFlow::Value value(tok->tokAt(2)->astOperand1()->getKnownIntValue());
value.setKnown();
- setTokenValue(tok->tokAt(2), std::move(value), settings, isInitList);
+ setTokenValue(tok->tokAt(2), std::move(value), settings);
}
}
return tok->next();
@@ -1351,16 +1350,8 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b
static void valueFlowNumber(TokenList &tokenlist, const Settings* settings)
{
- bool isInitList = false;
- const Token* endInit{};
for (Token *tok = tokenlist.front(); tok;) {
- if (!isInitList && tok->str() == "{" && (Token::simpleMatch(tok->astOperand1(), ",") || Token::simpleMatch(tok->astOperand2(), ","))) {
- isInitList = true;
- endInit = tok->link();
- }
- tok = valueFlowSetConstantValue(tok, settings, tokenlist.isCPP(), isInitList);
- if (isInitList && tok == endInit)
- isInitList = false;
+ tok = valueFlowSetConstantValue(tok, settings, tokenlist.isCPP());
}
if (tokenlist.isCPP()) {
@@ -3064,12 +3055,11 @@ struct SingleValueFlowAnalyzer : ValueFlowAnalyzer {
}
bool isGlobal() const override {
- for (const auto&p:getVars()) {
+ const auto& vars = getVars();
+ return std::any_of(vars.cbegin(), vars.cend(), [] (const std::pair& p) {
const Variable* var = p.second;
- if (!var->isLocal() && !var->isArgument() && !var->isConst())
- return true;
- }
- return false;
+ return !var->isLocal() && !var->isArgument() && !var->isConst();
+ });
}
bool lowerToPossible() override {
@@ -5848,6 +5838,7 @@ static bool intersects(const C1& c1, const C2& c2)
{
if (c1.size() > c2.size())
return intersects(c2, c1);
+ // NOLINTNEXTLINE(readability-use-anyofallof) - TODO: fix if possible / also Cppcheck false negative
for (auto&& x : c1) {
if (c2.find(x) != c2.end())
return true;
@@ -8048,7 +8039,7 @@ static void valueFlowUninit(TokenList& tokenlist, const Settings* settings)
}
}
-static bool isContainerSizeChanged(nonneg int varId,
+static bool isContainerSizeChanged(const Token* expr,
const Token* start,
const Token* end,
int indirect,
@@ -8097,7 +8088,7 @@ static bool isContainerSizeChangedByFunction(const Token* tok,
if (!arg->nameToken())
return false;
if (depth > 0)
- return isContainerSizeChanged(arg->declarationId(),
+ return isContainerSizeChanged(arg->nameToken(),
scope->bodyStart,
scope->bodyEnd,
addressOf ? indirect + 1 : indirect,
@@ -8351,7 +8342,7 @@ bool ValueFlow::isContainerSizeChanged(const Token* tok, int indirect, const Set
return isContainerSizeChangedByFunction(tok, indirect, settings, depth);
}
-static bool isContainerSizeChanged(nonneg int varId,
+static bool isContainerSizeChanged(const Token* expr,
const Token* start,
const Token* end,
int indirect,
@@ -8359,7 +8350,7 @@ static bool isContainerSizeChanged(nonneg int varId,
int depth)
{
for (const Token *tok = start; tok != end; tok = tok->next()) {
- if (tok->varId() != varId)
+ if (tok->exprId() != expr->exprId() && !isAliasOf(tok, expr))
continue;
if (ValueFlow::isContainerSizeChanged(tok, indirect, settings, depth))
return true;
@@ -9466,6 +9457,18 @@ void ValueFlow::setValues(TokenList& tokenlist,
for (Token* tok = tokenlist.front(); tok; tok = tok->next())
tok->clearValueFlow();
+ // commas in init..
+ for (Token* tok = tokenlist.front(); tok; tok = tok->next()) {
+ if (tok->str() != "{" || !tok->astOperand1())
+ continue;
+ for (Token* tok2 = tok->next(); tok2 != tok->link(); tok2 = tok2->next()) {
+ if (tok2->link() && Token::Match(tok2, "[{[(<]"))
+ tok2 = tok2->link();
+ else if (tok2->str() == ",")
+ tok2->isInitComma(true);
+ }
+ }
+
ValueFlowPassRunner runner{ValueFlowState{tokenlist, symboldatabase, errorLogger, settings}, timerResults};
runner.run_once({
VFA(valueFlowEnumValue(symboldatabase, settings)),
diff --git a/releasenotes.txt b/releasenotes.txt
index c54c20094a9..e302a8481f3 100644
--- a/releasenotes.txt
+++ b/releasenotes.txt
@@ -10,8 +10,12 @@ Improved checking:
- constParameter*/constVariable* checks find more instances of pointers/references that can be const, e.g. when calling library functions
GUI:
+- Show in statistics which checkers have been activated in latest analysis
+- Make it more visible if there has been critical errors that caused checkers to be skipped
Changed interface:
+- Write how many checkers was activated after a run
+- Added --checkers-report that can be used to generate a report in a file that shows what checkers was activated and disabled
Deprecations:
- The qmake build system has been deprecated and will be removed in a future version.
@@ -20,3 +24,4 @@ Deprecations:
Other:
- "USE_QT6=On" will no longer fallback to Qt5 when Qt6 is not found.
+- When the execution of an addon fails with an exitcode it will now result in an 'internalError' instead of being silently ignored.
\ No newline at end of file
diff --git a/test/cli/test-other.py b/test/cli/test-other.py
index a630699a115..2d58b2584f4 100644
--- a/test/cli/test-other.py
+++ b/test/cli/test-other.py
@@ -141,3 +141,82 @@ def test_progress_j(tmpdir):
assert exitcode == 0
assert stdout == "Checking {} ...\n".format(test_file)
assert stderr == ""
+
+
+@pytest.mark.timeout(10)
+def test_slow_array_many_floats(tmpdir):
+ # 11649
+ # cppcheck valueflow takes a long time when an array has many floats
+ filename = os.path.join(tmpdir, 'hang.c')
+ with open(filename, 'wt') as f:
+ f.write("const float f[] = {\n")
+ for i in range(20000):
+ f.write(' 13.6f,\n')
+ f.write("};\n")
+ cppcheck([filename]) # should not take more than ~1 second
+
+
+@pytest.mark.timeout(10)
+def test_slow_array_many_strings(tmpdir):
+ # 11901
+ # cppcheck valueflow takes a long time when analyzing a file with many strings
+ filename = os.path.join(tmpdir, 'hang.c')
+ with open(filename, 'wt') as f:
+ f.write("const char *strings[] = {\n")
+ for i in range(20000):
+ f.write(' "abc",\n')
+ f.write("};\n")
+ cppcheck([filename]) # should not take more than ~1 second
+
+
+def test_execute_addon_failure(tmpdir):
+ test_file = os.path.join(tmpdir, 'test.cpp')
+ with open(test_file, 'wt') as f:
+ f.write("""
+ void f();
+ """)
+
+ args = ['--addon=naming', test_file]
+
+ # provide empty PATH environment variable so python is not found and execution of addon fails
+ env = {'PATH': ''}
+ _, _, stderr = cppcheck(args, env)
+ assert stderr == '{}:0:0: error: Bailing out from analysis: Checking file failed: Failed to auto detect python [internalError]\n\n^\n'.format(test_file)
+
+
+def test_execute_addon_failure_2(tmpdir):
+ test_file = os.path.join(tmpdir, 'test.cpp')
+ with open(test_file, 'wt') as f:
+ f.write("""
+ void f();
+ """)
+
+ # specify non-existent python executbale so execution of addon fails
+ args = ['--addon=naming', '--addon-python=python5.x', test_file]
+
+ _, _, stderr = cppcheck(args)
+ # /tmp/pytest-of-sshuser/pytest-215/test_execute_addon_failure_20/test.cpp:0:0: error: Bailing out from analysis: Checking file failed: Failed to execute addon 'naming' (command: 'python5.x /mnt/s/GitHub/cppcheck-fw/addons/runaddon.py /mnt/s/GitHub/cppcheck-fw/addons/naming.py --cli /tmp/pytest-of-sshuser/pytest-215/test_execute_addon_failure_20/test.cpp.7306.dump'). Exitcode is nonzero. [internalError]\n\n^\n
+ # "C:\\Users\\Quotenjugendlicher\\AppData\\Local\\Temp\\pytest-of-Quotenjugendlicher\\pytest-15\\test_execute_addon_failure_20\\test.cpp:0:0: error: Bailing out from analysis: Checking file failed: Failed to execute addon (command: 'python5.x S:\\GitHub\\cppcheck-fw\\bin\\debug\\addons\\runaddon.py S:\\GitHub\\cppcheck-fw\\bin\\debug\\addons\\naming.py --cli C:\\Users\\Quotenjugendlicher\\AppData\\Local\\Temp\\pytest-of-Quotenjugendlicher\\pytest-15\\test_execute_addon_failure_20\\test.cpp.9892.dump'). Exitcode is nonzero. [internalError]\n\n^\n
+ assert stderr.startswith('{}:0:0: error: Bailing out from analysis: Checking file failed: Failed to execute addon \'naming\' (command: \'python5.x '.format(test_file))
+ assert stderr.endswith(' [internalError]\n\n^\n')
+
+
+# TODO: find a test case which always fails
+@pytest.mark.skip
+def test_internal_error(tmpdir):
+ test_file = os.path.join(tmpdir, 'test.cpp')
+ with open(test_file, 'wt') as f:
+ f.write("""
+#include
+
+void f() {
+ double gc = 3333.3333;
+ char stat[80];
+ sprintf(stat,"'%2.1f'",gc);
+}
+ """)
+
+ args = [test_file]
+
+ _, _, stderr = cppcheck(args)
+ assert stderr == '{}:0:0: error: Bailing from out analysis: Checking file failed: converting \'1f\' to integer failed - not an integer [internalError]\n\n^\n'.format(test_file)
\ No newline at end of file
diff --git a/test/cli/testutils.py b/test/cli/testutils.py
index c1a1455eab7..1e53c65db48 100644
--- a/test/cli/testutils.py
+++ b/test/cli/testutils.py
@@ -63,12 +63,12 @@ def lookup_cppcheck_exe():
# Run Cppcheck with args
-def cppcheck(args):
+def cppcheck(args, env=None):
exe = lookup_cppcheck_exe()
assert exe is not None, 'no cppcheck binary found'
logging.info(exe + ' ' + ' '.join(args))
- p = subprocess.Popen([exe] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ p = subprocess.Popen([exe] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
comm = p.communicate()
stdout = comm[0].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n')
stderr = comm[1].decode(encoding='utf-8', errors='ignore').replace('\r\n', '\n')
diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp
index 55925648811..418025e33c9 100644
--- a/test/testconstructors.cpp
+++ b/test/testconstructors.cpp
@@ -116,6 +116,7 @@ class TestConstructors : public TestFixture {
TEST_CASE(initvar_chained_assign); // BUG 2270433
TEST_CASE(initvar_2constructors); // BUG 2270353
TEST_CASE(initvar_constvar);
+ TEST_CASE(initvar_mutablevar);
TEST_CASE(initvar_staticvar);
TEST_CASE(initvar_brace_init);
TEST_CASE(initvar_union);
@@ -1194,6 +1195,18 @@ class TestConstructors : public TestFixture {
}
+ void initvar_mutablevar() {
+ check("class Foo {\n"
+ "public:\n"
+ " Foo() { update(); }\n"
+ "private:\n"
+ " void update() const;\n"
+ " mutable int x;\n"
+ "};");
+ ASSERT_EQUALS("", errout.str());
+ }
+
+
void initvar_staticvar() {
check("class Fred\n"
"{\n"
diff --git a/test/testother.cpp b/test/testother.cpp
index 4f5782e6d90..829265a3790 100644
--- a/test/testother.cpp
+++ b/test/testother.cpp
@@ -11033,6 +11033,18 @@ class TestOther : public TestFixture {
"}");
ASSERT_EQUALS("", errout.str());
+ // #11894
+ check("struct S {\n"
+ " int *p, n;\n"
+ "};\n"
+ "S* g() {\n"
+ " S* s = static_cast(calloc(1, sizeof(S)));\n"
+ " s->n = 100;\n"
+ " s->p = static_cast(malloc(s->n * sizeof(int)));\n"
+ " return s;\n"
+ "}\n");
+ ASSERT_EQUALS("", errout.str());
+
// #11679
check("bool g(int);\n"
"void h(int);\n"
@@ -11041,6 +11053,20 @@ class TestOther : public TestFixture {
" if (g(k(i))) {}\n"
"}\n");
ASSERT_EQUALS("", errout.str());
+
+ // #11889
+ check("struct S {\n"
+ " int a[5];\n"
+ " void f(int i);\n"
+ "}\n"
+ "void g(int);\n"
+ "void S::f(int i) {\n"
+ " if (a[i] == 1) {\n"
+ " a[i] = 0;\n"
+ " g(a[i]);\n"
+ " }\n"
+ "}\n");
+ ASSERT_EQUALS("", errout.str());
}
void knownArgumentHiddenVariableExpression() {
diff --git a/test/testrunner.vcxproj.filters b/test/testrunner.vcxproj.filters
index db85b4d9e37..7aa2676a830 100644
--- a/test/testrunner.vcxproj.filters
+++ b/test/testrunner.vcxproj.filters
@@ -256,6 +256,9 @@
Source Files
+
+ Source Files
+
diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp
index 13c7846061f..aaf934775b4 100644
--- a/test/testsymboldatabase.cpp
+++ b/test/testsymboldatabase.cpp
@@ -442,6 +442,7 @@ class TestSymbolDatabase : public TestFixture {
TEST_CASE(findFunction47);
TEST_CASE(findFunction48);
TEST_CASE(findFunction49); // #11888
+ TEST_CASE(findFunction50); // #11904 - method with same name and arguments in derived class
TEST_CASE(findFunctionContainer);
TEST_CASE(findFunctionExternC);
TEST_CASE(findFunctionGlobalScope); // ::foo
@@ -7304,6 +7305,26 @@ class TestSymbolDatabase : public TestFixture {
ASSERT_EQUALS(4, ftok->function()->tokenDef->linenr());
}
+ void findFunction50() {
+ {
+ GET_SYMBOL_DB("struct B { B(); void init(unsigned int value); };\n"
+ "struct D: B { D(); void init(unsigned int value); };\n"
+ "D::D() { init(0); }\n"
+ "void D::init(unsigned int value) {}\n");
+ const Token* call = Token::findsimplematch(tokenizer.tokens(), "init ( 0 ) ;");
+ ASSERT(call && call->function() && call->function()->functionScope);
+ }
+
+ {
+ GET_SYMBOL_DB("struct B { B(); void init(unsigned int value); };\n"
+ "struct D: B { D(); void init(unsigned int value); };\n"
+ "D::D() { init(0ULL); }\n"
+ "void D::init(unsigned int value) {}\n");
+ const Token* call = Token::findsimplematch(tokenizer.tokens(), "init ( 0ULL ) ;");
+ ASSERT(call && call->function() && call->function()->functionScope);
+ }
+ }
+
void findFunctionContainer() {
{
GET_SYMBOL_DB("void dostuff(std::vector v);\n"
diff --git a/test/testutils.cpp b/test/testutils.cpp
index 09f92d3815a..bdc095f54a0 100644
--- a/test/testutils.cpp
+++ b/test/testutils.cpp
@@ -22,6 +22,8 @@
#include
#include
#include
+#include
+#include
#include
#include
@@ -36,6 +38,7 @@ class TestUtils : public TestFixture {
TEST_CASE(isStringLiteral);
TEST_CASE(isCharLiteral);
TEST_CASE(strToInt);
+ TEST_CASE(id_string);
}
void isValidGlobPattern() const {
@@ -330,6 +333,18 @@ class TestUtils : public TestFixture {
ASSERT_EQUALS("out of range (stoull)", err);
}
}
+
+ void id_string() const
+ {
+ ASSERT_EQUALS("0", id_string_i(0));
+ ASSERT_EQUALS("f1", id_string_i(0xF1));
+ ASSERT_EQUALS("123", id_string_i(0x123));
+ ASSERT_EQUALS("1230", id_string_i(0x1230));
+ ASSERT_EQUALS(std::string(8,'f'), id_string_i(0xffffffffU));
+ if (sizeof(void*) == 8) {
+ ASSERT_EQUALS(std::string(16,'f'), id_string_i(~0ULL));
+ }
+ }
};
REGISTER_TEST(TestUtils)
diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp
index e1302d9ce73..788b96f7623 100644
--- a/test/testvalueflow.cpp
+++ b/test/testvalueflow.cpp
@@ -6643,6 +6643,18 @@ class TestValueFlow : public TestFixture {
code = "int f() { auto a = std::array{}; return a[1]; }";
ASSERT_EQUALS("values.size():0", isKnownContainerSizeValue(tokenValues(code, "a ["), 0));
+
+ code = "void g(std::vector* w) {\n"
+ " std::vector &r = *w;\n"
+ " r.push_back(0);\n"
+ "}\n"
+ "int f() {\n"
+ " std::vector v;\n"
+ " g(&v);\n"
+ " return v[0];\n"
+ "}\n";
+ ASSERT(!isKnownContainerSizeValue(tokenValues(code, "v ["), 0).empty());
+ ASSERT(!isPossibleContainerSizeValue(tokenValues(code, "v ["), 0).empty());
}
void valueFlowContainerElement()
diff --git a/tools/get_checkers.py b/tools/get_checkers.py
index b43e457a08f..7dbdbf36801 100644
--- a/tools/get_checkers.py
+++ b/tools/get_checkers.py
@@ -43,27 +43,400 @@
print('static std::map premiumCheckers{')
premium_checkers = """
-$ grep logChecker *.cpp | sed 's/.*logChecker/logChecker/'
-logChecker("CheckBufferOverrun::addressOfPointerArithmetic"); // warning
-logChecker("CheckBufferOverrun::negativeBufferSizeCheckedNonZero"); // warning
-logChecker("CheckBufferOverrun::negativeBufferSizeCheckedNonZero"); // warning
-logChecker("CheckHang::infiniteLoop");
-logChecker("CheckHang::infiniteLoopContinue");
-logChecker("CheckOther::arrayPointerComparison"); // style
-logChecker("CheckOther::knownResult"); // style
-logChecker("CheckOther::lossOfPrecision"); // style
-logChecker("CheckOther::pointerCast"); // style
-logChecker("CheckOther::reassignInLoop"); // style
-logChecker("CheckOther::unreachableCode"); // style
-logChecker("CheckStrictAlias::strictAliasCondition"); // warning
-logChecker("CheckUninitVar::uninitvar");
-logChecker("CheckUninitVar::uninitmember");
-logChecker("CheckUnusedVar::unreadVariable"); // style
-logChecker("CheckUnusedVar::unusedPrivateMember"); // style
+$ grep logChecker src/*.cpp | sed 's/.*logChecker/logChecker/' | sort > 1.txt
+logChecker("Autosar: A0-1-3"); // style
+logChecker("Autosar: A0-4-2"); // style
+logChecker("Autosar: A0-4-4"); // style
+logChecker("Autosar: A10-1-1"); // style
+logChecker("Autosar: A11-0-2"); // style
+logChecker("Autosar: A11-3-1"); // style
+logChecker("Autosar: A13-2-1"); // style
+logChecker("Autosar: A13-2-3"); // style
+logChecker("Autosar: A13-5-2"); // style
+logChecker("Autosar: A13-5-5"); // style
+logChecker("Autosar: A15-1-2"); // style
+logChecker("Autosar: A15-3-5"); // style
+logChecker("Autosar: A16-6-1"); // style
+logChecker("Autosar: A16-7-1"); // style
+logChecker("Autosar: A18-0-3"); // style
+logChecker("Autosar: A18-1-1"); // style
+logChecker("Autosar: A18-1-2"); // style
+logChecker("Autosar: A18-1-3"); // style
+logChecker("Autosar: A18-5-1"); // style
+logChecker("Autosar: A18-9-1"); // style
+logChecker("Autosar: A2-11-1"); // style
+logChecker("Autosar: A2-13-1"); // style
+logChecker("Autosar: A2-13-3"); // style
+logChecker("Autosar: A2-13-5"); // style
+logChecker("Autosar: A2-13-6"); // style
+logChecker("Autosar: A2-5-2"); // style
+logChecker("Autosar: A3-1-3"); // style
+logChecker("Autosar: A3-1-4"); // style
+logChecker("Autosar: A3-3-1"); // style
+logChecker("Autosar: A4-10-1"); // style
+logChecker("Autosar: A4-7-1"); // style
+logChecker("Autosar: A5-0-2"); // style
+logChecker("Autosar: A5-0-3"); // style
+logChecker("Autosar: A5-0-4"); // style
+logChecker("Autosar: A5-1-1"); // style
+logChecker("Autosar: A5-1-2"); // style
+logChecker("Autosar: A5-1-3"); // style
+logChecker("Autosar: A5-16-1"); // style
+logChecker("Autosar: A5-1-6"); // style
+logChecker("Autosar: A5-1-7"); // style
+logChecker("Autosar: A5-2-1"); // style
+logChecker("Autosar: A5-2-4"); // style
+logChecker("Autosar: A6-5-3"); // style
+logChecker("Autosar: A7-1-4"); // style
+logChecker("Autosar: A7-1-6"); // style
+logChecker("Autosar: A7-1-7"); // style
+logChecker("Autosar: A8-4-1"); // style
+logChecker("Autosar: A8-5-3"); // style
+logChecker("Autosar: A9-3-1"); // style
+logChecker("Cert C: ARR30-C"); // warning
+logChecker("Cert C: ARR32-C"); // warning
+logChecker("Cert C: ARR37-C"); // warning
+logChecker("Cert C: ARR38-C");
+logChecker("Cert C: ARR39-C"); // warning
+logChecker("Cert C: CON30-C"); // style
+logChecker("Cert C: CON31-C"); // style
+logChecker("Cert C: CON32-C"); // style
+logChecker("Cert C: CON33-C"); // style
+logChecker("Cert C: CON34-C"); // warning
+logChecker("Cert C: CON35-C"); // warning
+logChecker("Cert C: CON36-C"); // style
+logChecker("Cert C: CON37-C"); // style
+logChecker("Cert C: CON38-C"); // warning
+logChecker("Cert C: CON39-C"); // warning
+logChecker("Cert C: CON40-C"); // warning
+logChecker("Cert C: CON41-C"); // style
+logChecker("Cert C++: CON51-CPP");
+logChecker("Cert C++: CON52-CPP"); // style
+logChecker("Cert C++: CON53-CPP"); // style
+logChecker("Cert C++: CON54-CPP"); // style
+logChecker("Cert C++: CON55-CPP"); // style
+logChecker("Cert C++: CON56-CPP");
+logChecker("Cert C++: CTR50-CPP");
+logChecker("Cert C++: CTR52-CPP");
+logChecker("Cert C++: CTR53-CPP");
+logChecker("Cert C++: CTR56-CPP"); // style
+logChecker("Cert C++: CTR57-CPP");
+logChecker("Cert C++: CTR58-CPP");
+logChecker("Cert C: DCL31-C"); // style
+logChecker("Cert C: DCL36-C"); // style
+logChecker("Cert C: DCL37-C"); // style
+logChecker("Cert C: DCL38-C"); // style
+logChecker("Cert C: DCL39-C"); // style
+logChecker("Cert C: DCL40-C"); // style
+logChecker("Cert C: DCL41-C"); // style
+logChecker("Cert C++: DCL50-CPP"); // style
+logChecker("Cert C++: DCL51-CPP"); // style
+logChecker("Cert C++: DCL52-CPP"); // style
+logChecker("Cert C++: DCL53-CPP"); // style
+logChecker("Cert C++: DCL54-CPP");
+logChecker("Cert C++: DCL56-CPP");
+logChecker("Cert C++: DCL58-CPP"); // style
+logChecker("Cert C++: DCL59-CPP"); // style
+logChecker("Cert C: ENV30-C"); // style
+logChecker("Cert C: ENV31-C"); // style
+logChecker("Cert C: ENV32-C"); // style
+logChecker("Cert C: ENV33-C"); // style
+logChecker("Cert C: ENV34-C"); // style
+logChecker("Cert C: ERR30-C"); // warning
+logChecker("Cert C: ERR32-C"); // warning
+logChecker("Cert C: ERR33-C"); // warning
+logChecker("Cert C++: ERR50-CPP");
+logChecker("Cert C++: ERR51-CPP"); // style
+logChecker("Cert C++: ERR52-CPP"); // style
+logChecker("Cert C++: ERR53-CPP");
+logChecker("Cert C++: ERR54-CPP");
+logChecker("Cert C++: ERR55-CPP");
+logChecker("Cert C++: ERR56-CPP");
+logChecker("Cert C++: ERR58-CPP");
+logChecker("Cert C++: ERR59-CPP"); // warning
+logChecker("Cert C++: ERR60-CPP"); // warning
+logChecker("Cert C++: ERR61-CPP"); // style
+logChecker("Cert C++: ERR62-CPP"); // style
+logChecker("Cert C: EXP32-C"); // warning
+logChecker("Cert C: EXP35-C");
+logChecker("Cert C: EXP36-C"); // style
+logChecker("Cert C: EXP37-C"); // style
+logChecker("Cert C: EXP39-C"); // style
+logChecker("Cert C: EXP40-C"); // style
+logChecker("Cert C: EXP42-C"); // style
+logChecker("Cert C: EXP43-C"); // style
+logChecker("Cert C: EXP45-C"); // warning
+logChecker("Cert C++: EXP50-CPP");
+logChecker("Cert C++: EXP51-CPP");
+logChecker("Cert C++: EXP55-CPP");
+logChecker("Cert C++: EXP56-CPP");
+logChecker("Cert C++: EXP57-CPP"); // style
+logChecker("Cert C++: EXP58-CPP"); // style
+logChecker("Cert C++: EXP59-CPP");
+logChecker("Cert C: FIO30-C"); // warning
+logChecker("Cert C: FIO32-C"); // style
+logChecker("Cert C: FIO34-C"); // style
+logChecker("Cert C: FIO37-C");
+logChecker("Cert C: FIO38-C"); // style
+logChecker("Cert C: FIO40-C"); // style
+logChecker("Cert C: FIO41-C"); // style
+logChecker("Cert C: FIO44-C"); // warning
+logChecker("Cert C: FIO45-C"); // warning
+logChecker("Cert C++: FIO51-CPP"); // style
+logChecker("Cert C: FLP30-C"); // warning
+logChecker("Cert C: FLP36-C"); // portability
+logChecker("Cert C: FLP37-C"); // style
+logChecker("Cert C: INT30-C"); // warning
+logChecker("Cert C: INT31-C"); // warning
+logChecker("Cert C: INT32-C"); // warning
+logChecker("Cert C: INT33-C"); // warning
+logChecker("Cert C: INT34-C"); // warning
+logChecker("Cert C: INT35-C"); // warning
+logChecker("Cert C: INT36-C"); // warning
+logChecker("Cert C++: INT50-CPP"); // style
+logChecker("Cert C: MEM33-C"); // style
+logChecker("Cert C: MEM35-C"); // warning
+logChecker("Cert C: MEM36-C"); // warning
+logChecker("Cert C++: MEM52-CPP");
+logChecker("Cert C++: MEM53-CPP");
+logChecker("Cert C++: MEM54-CPP");
+logChecker("Cert C++: MEM55-CPP");
+logChecker("Cert C++: MEM57-CPP"); // style
+logChecker("Cert C: MSC30-C"); // style
+logChecker("Cert C: MSC32-C"); // style
+logChecker("Cert C: MSC33-C"); // style
+logChecker("Cert C: MSC38-C"); // warning
+logChecker("Cert C: MSC39-C"); // warning
+logChecker("Cert C: MSC40-C"); // warning
+logChecker("Cert C++: MSC50-CPP"); // style
+logChecker("Cert C++: MSC51-CPP"); // style
+logChecker("Cert C++: MSC53-CPP");
+logChecker("Cert C++: MSC54-CPP"); // style
+logChecker("Cert C++: OOP51-CPP");
+logChecker("Cert C++: OOP55-CPP");
+logChecker("Cert C++: OOP56-CPP");
+logChecker("Cert C++: OOP57-CPP");
+logChecker("Cert C++: OOP58-CPP"); // style
+logChecker("Cert C: PRE31-C"); // style
+logChecker("Cert C: SIG30-C"); // style
+logChecker("Cert C: SIG31-C"); // warning
+logChecker("Cert C: SIG34-C"); // style
+logChecker("Cert C: SIG35-C"); // warning
+logChecker("Cert C: STR31-C"); // warning
+logChecker("Cert C: STR32-C"); // warning
+logChecker("Cert C: STR34-C"); // warning
+logChecker("Cert C: STR38-C"); // style
+logChecker("Cert C++: STR50-CPP");
+logChecker("Cert C++: STR53-CPP");
+logChecker("Misra C: 10.1"); // style
+logChecker("Misra C: 10.2"); // style
+logChecker("Misra C: 10.3"); // style
+logChecker("Misra C: 10.4"); // style
+logChecker("Misra C: 10.5"); // style
+logChecker("Misra C: 10.6"); // style
+logChecker("Misra C: 10.7"); // style
+logChecker("Misra C: 10.8"); // style
+logChecker("Misra C: 11.10"); // style
+logChecker("Misra C: 12.6");
+logChecker("Misra C: 1.5"); // style
+logChecker("Misra C: 17.10"); // style
+logChecker("Misra C: 17.11"); // style
+logChecker("Misra C: 17.12"); // style
+logChecker("Misra C: 17.9"); // style
+logChecker("Misra C: 18.10"); // style
+logChecker("Misra C: 18.9"); // style
+logChecker("Misra C: 21.12"); // style
+logChecker("Misra C: 21.22"); // style
+logChecker("Misra C: 21.23"); // style
+logChecker("Misra C: 21.24"); // style
+logChecker("Misra C: 21.25"); // warning
+logChecker("Misra C: 21.26"); // warning
+logChecker("Misra C: 22.11");
+logChecker("Misra C: 22.12"); // style
+logChecker("Misra C: 22.13"); // style
+logChecker("Misra C: 22.14"); // style
+logChecker("Misra C: 22.15"); // style
+logChecker("Misra C: 22.16"); // warning
+logChecker("Misra C: 22.17"); // warning
+logChecker("Misra C: 22.18"); // warning
+logChecker("Misra C: 22.19"); // warning
+logChecker("Misra C: 22.20"); // style
+logChecker("Misra C: 23.1"); // style
+logChecker("Misra C: 23.2"); // style
+logChecker("Misra C: 23.3"); // style
+logChecker("Misra C: 23.4"); // style
+logChecker("Misra C: 23.5"); // style
+logChecker("Misra C: 23.6"); // style
+logChecker("Misra C: 23.7"); // style
+logChecker("Misra C: 23.8"); // style
+logChecker("Misra C: 6.3"); // style
+logChecker("Misra C: 7.5"); // style
+logChecker("Misra C: 7.6"); // style
+logChecker("Misra C: 8.10"); // style
+logChecker("Misra C: 8.15"); // style
+logChecker("Misra C: 8.16"); // style
+logChecker("Misra C: 8.17"); // style
+logChecker("Misra C: 9.6"); // style
+logChecker("Misra C: 9.7");
+logChecker("Misra C++: M0-1-11"); // style
+logChecker("Misra C++: M0-1-12"); // style
+logChecker("Misra C++: M0-1-4"); // style
+logChecker("Misra C++: M0-1-5"); // style
+logChecker("Misra C++: M0-1-7"); // style
+logChecker("Misra C++: M0-1-8"); // style
+logChecker("Misra C++: M10-1-1"); // style
+logChecker("Misra C++: M10-1-2"); // style
+logChecker("Misra C++: M10-1-3"); // style
+logChecker("Misra C++: M10-2-1"); // style
+logChecker("Misra C++: M10-3-3"); // style
+logChecker("Misra C++: M11-0-1"); // style
+logChecker("Misra C++: M12-8-2"); // style
+logChecker("Misra C++: M14-5-1"); // warning
+logChecker("Misra C++: M14-5-2"); // warning
+logChecker("Misra C++: M14-5-3"); // warning
+logChecker("Misra C++: M14-6-1"); // warning
+logChecker("Misra C++: M14-7-1"); // style
+logChecker("Misra C++: M14-7-2"); // style
+logChecker("Misra C++: M15-0-3");
+logChecker("Misra C++: M15-1-1");
+logChecker("Misra C++: M15-1-2"); // style
+logChecker("Misra C++: M15-1-3"); // style
+logChecker("Misra C++: M15-3-2"); // warning
+logChecker("Misra C++: M15-3-3");
+logChecker("Misra C++: M15-4-1"); // style
+logChecker("Misra C++: M16-0-1"); // style
+logChecker("Misra C++: M16-0-2"); // style
+logChecker("Misra C++: M16-0-3"); // style
+logChecker("Misra C++: M16-0-4"); // style
+logChecker("Misra C++: M16-1-1"); // style
+logChecker("Misra C++: M16-2-1"); // style
+logChecker("Misra C++: M16-2-2"); // style
+logChecker("Misra C++: M16-2-3"); // style
+logChecker("Misra C++: M16-2-4"); // style
+logChecker("Misra C++: M16-2-5"); // style
+logChecker("Misra C++: M16-2-6"); // style
+logChecker("Misra C++: M16-3-1"); // style
+logChecker("Misra C++: M16-3-2"); // style
+logChecker("Misra C++: M17-0-1"); // style
+logChecker("Misra C++: M17-0-2"); // style
+logChecker("Misra C++: M17-0-3"); // style
+logChecker("Misra C++: M17-0-5"); // style
+logChecker("Misra C++: M18-0-1"); // style
+logChecker("Misra C++: M18-0-2"); // style
+logChecker("Misra C++: M18-0-3"); // style
+logChecker("Misra C++: M18-0-4"); // style
+logChecker("Misra C++: M18-0-5"); // style
+logChecker("Misra C++: M18-2-1"); // style
+logChecker("Misra C++: M18-4-1"); // style
+logChecker("Misra C++: M18-7-1"); // style
+logChecker("Misra C++: M19-3-1"); // style
+logChecker("Misra C++: M2-10-1"); // style
+logChecker("Misra C++: M2-10-3"); // style
+logChecker("Misra C++: M2-10-4"); // style
+logChecker("Misra C++: M2-10-5"); // style
+logChecker("Misra C++: M2-10-6"); // style
+logChecker("Misra C++: M2-13-4"); // style
+logChecker("Misra C++: M2-13-5"); // style
+logChecker("Misra C++: M27-0-1"); // style
+logChecker("Misra C++: M2-7-1"); // style
+logChecker("Misra C++: M2-7-2"); // style
+logChecker("Misra C++: M2-7-3"); // style
+logChecker("Misra C++: M3-1-1"); // style
+logChecker("Misra C++: M3-1-2"); // style
+logChecker("Misra C++: M3-1-3"); // style
+logChecker("Misra C++: M3-2-1");
+logChecker("Misra C++: M3-3-1"); // style
+logChecker("Misra C++: M3-3-2"); // style
+logChecker("Misra C++: M3-9-1"); // style
+logChecker("Misra C++: M3-9-2"); // style
+logChecker("Misra C++: M3-9-3"); // style
+logChecker("Misra C++: M4-10-1"); // style
+logChecker("Misra C++: M4-10-2"); // style
+logChecker("Misra C++: M4-5-1"); // style
+logChecker("Misra C++: M4-5-2"); // style
+logChecker("Misra C++: M4-5-3"); // style
+logChecker("Misra C++: M5-0-10"); // style
+logChecker("Misra C++: M5-0-11"); // style
+logChecker("Misra C++: M5-0-12"); // style
+logChecker("Misra C++: M5-0-14"); // style
+logChecker("Misra C++: M5-0-15"); // style
+logChecker("Misra C++: M5-0-20"); // style
+logChecker("Misra C++: M5-0-21"); // style
+logChecker("Misra C++: M5-0-2"); // style
+logChecker("Misra C++: M5-0-3"); // style
+logChecker("Misra C++: M5-0-4"); // style
+logChecker("Misra C++: M5-0-5"); // style
+logChecker("Misra C++: M5-0-6"); // style
+logChecker("Misra C++: M5-0-7"); // style
+logChecker("Misra C++: M5-0-8"); // style
+logChecker("Misra C++: M5-0-9"); // style
+logChecker("Misra C++: M5-2-10"); // style
+logChecker("Misra C++: M5-2-11"); // style
+logChecker("Misra C++: M5-2-12"); // style
+logChecker("Misra C++: M5-2-1"); // style
+logChecker("Misra C++: M5-2-2"); // style
+logChecker("Misra C++: M5-2-3"); // style
+logChecker("Misra C++: M5-2-5"); // style
+logChecker("Misra C++: M5-2-6"); // style
+logChecker("Misra C++: M5-2-7"); // style
+logChecker("Misra C++: M5-2-8"); // style
+logChecker("Misra C++: M5-2-9"); // style
+logChecker("Misra C++: M5-3-1"); // style
+logChecker("Misra C++: M5-3-2"); // style
+logChecker("Misra C++: M5-3-3"); // style
+logChecker("Misra C++: M6-2-3"); // style
+logChecker("Misra C++: M6-4-4"); // style
+logChecker("Misra C++: M6-4-6"); // style
+logChecker("Misra C++: M6-4-7"); // style
+logChecker("Misra C++: M6-4-8"); // style
+logChecker("Misra C++: M6-5-1"); // style
+logChecker("Misra C++: M6-5-2"); // style
+logChecker("Misra C++: M6-5-3"); // style
+logChecker("Misra C++: M6-5-4"); // style
+logChecker("Misra C++: M6-5-5"); // style
+logChecker("Misra C++: M6-5-6"); // style
+logChecker("Misra C++: M6-6-1"); // style
+logChecker("Misra C++: M6-6-3"); // style
+logChecker("Misra C++: M6-6-4"); // style
+logChecker("Misra C++: M6-6-5"); // style
+logChecker("Misra C++: M7-2-1"); // style
+logChecker("Misra C++: M7-3-1"); // style
+logChecker("Misra C++: M7-3-2"); // style
+logChecker("Misra C++: M7-3-3"); // style
+logChecker("Misra C++: M7-3-4"); // style
+logChecker("Misra C++: M7-3-5"); // style
+logChecker("Misra C++: M7-3-6"); // style
+logChecker("Misra C++: M7-4-2"); // style
+logChecker("Misra C++: M7-4-3"); // style
+logChecker("Misra C++: M7-5-3"); // style
+logChecker("Misra C++: M8-0-1"); // style
+logChecker("Misra C++: M8-3-1"); // style
+logChecker("Misra C++: M8-4-4"); // style
+logChecker("Misra C++: M9-3-1"); // style
+logChecker("Misra C++: M9-5-1"); // style
+logChecker("Misra C++: M9-6-2"); // style
+logChecker("Misra C++: M9-6-3"); // style
+logChecker("Misra C++: M9-6-4"); // style
+logChecker("PremiumCheckBufferOverrun::addressOfPointerArithmetic"); // warning
+logChecker("PremiumCheckBufferOverrun::negativeBufferSizeCheckedNonZero"); // warning
+logChecker("PremiumCheckBufferOverrun::negativeBufferSizeCheckedNonZero"); // warning
+logChecker("PremiumCheckHang::infiniteLoop");
+logChecker("PremiumCheckHang::infiniteLoopContinue");
+logChecker("PremiumCheckOther::arrayPointerComparison"); // style
+logChecker("PremiumCheckOther::knownResult"); // style
+logChecker("PremiumCheckOther::lossOfPrecision"); // style
+logChecker("PremiumCheckOther::pointerCast"); // style
+logChecker("PremiumCheckOther::reassignInLoop"); // style
+logChecker("PremiumCheckOther::unreachableCode"); // style
+logChecker("PremiumCheckStrictAlias::strictAliasCondition"); // warning
+logChecker("PremiumCheckUninitVar::uninitmember");
+logChecker("PremiumCheckUninitVar::uninitvar");
+logChecker("PremiumCheckUnusedVar::unreadVariable"); // style
+logChecker("PremiumCheckUnusedVar::unusedPrivateMember"); // style
"""
for line in premium_checkers.split('\n'):
- res = re.match(r'logChecker\("([:_a-zA-Z0-9]+)"\);.*', line)
+ res = re.match(r'logChecker\("([^"]+)"\);.*', line)
if res is None:
continue
if line.find('//') > 0: