From a8cb930a628f57c7644286e4fb0b71350ac95918 Mon Sep 17 00:00:00 2001 From: vodorok Date: Fri, 19 Aug 2022 16:03:46 +0200 Subject: [PATCH] [analyzer] Cppcheck support (#3680) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [analyzer] Cppcheck support This commit adds support for the Cppcheck analyzer. The following two commits are also squashed into this: * [test] Add new test cases for Cppcheck support * [analyzer] Check version compatibility This commit is the resurrection of works made by Márton Csordás. The original pull request #2290 had three more refactoring-related change sets which were omitted in this. Some changes were added in compared to the original commits: * The Cppcheck report converter is used to get the results in the result_handler. * The hash calculation logic has been uplifted to the latest one. * Some small small compatibility changes were added because of the changes in the code base. Further changes: * Cppcheck now works in a raw directory instead of directly into the workspace folder. * Exponential explosion of reports in plist files are now fixed. * Checker disable now works on native levels. * The `--disable ` now properly translates to `--suppress ` in the cppcheck invocation. * The current run configuration of cppcheck is `--enable=all`. Added two new input paramaters: * With `cppcheck-addons` extra cppcheck checkers can be specified. * With `cppcheck-libraries` the cppcheck library definitions can be added. Cppcheck reports have to be "fixed" for Codechecker to be able to properly interpret them. The actual error message must be added to any multistep report as a last bug path event. Cppcheck checkers are prefixed with the `cppcheck-` prefix. Co-authored-by: Márton Csordás Co-authored-by: bruntib Co-authored-by: vodorok --- .github/workflows/install-deps.sh | 3 +- .github/workflows/pypi.yml | 5 +- .../codechecker_analyzer/analysis_manager.py | 7 + .../analyzers/analyzer_base.py | 15 + .../analyzers/analyzer_types.py | 14 +- .../analyzers/clangsa/analyzer.py | 7 + .../analyzers/clangtidy/analyzer.py | 7 + .../analyzers/cppcheck/__init__.py | 7 + .../analyzers/cppcheck/analyzer.py | 357 ++++++++ .../analyzers/cppcheck/config_handler.py | 43 + .../analyzers/cppcheck/result_handler.py | 77 ++ .../analyzers/result_handler_base.py | 6 +- .../codechecker_analyzer/cmd/analyzers.py | 3 + analyzer/codechecker_analyzer/cmd/checkers.py | 6 +- analyzer/codechecker_analyzer/host_check.py | 2 +- .../test_analyze_and_parse.py | 3 +- .../analyze_and_parse/test_files/Makefile | 6 + .../test_files/cppcheck_args.cpp | 12 + .../test_files/cppcheck_args.noforward.output | 57 ++ .../test_files/cppcheck_args.output | 28 + .../test_files/cppcheck_multiple.cpp | 16 + .../test_files/cppcheck_multiple_error.output | 57 ++ .../cppcheck_multiple_warning.output | 57 ++ .../ctu_failure/test_ctu_failure.py | 8 +- config/labels/analyzers/cppcheck.json | 847 ++++++++++++------ config/package_layout.json | 3 +- docs/README.md | 5 +- .../checker_and_analyzer_configuration.md | 70 ++ docs/analyzer/user_guide.md | 30 +- docs/supported_code_analyzers.md | 3 +- .../analyzers/cppcheck/analyzer_result.py | 19 +- .../divide_zero.expected.plist | 38 + web/tests/functional/comment/__init__.py | 3 +- web/tests/functional/component/__init__.py | 3 +- web/tests/functional/db_cleanup/__init__.py | 3 +- web/tests/functional/delete_runs/__init__.py | 3 +- .../functional/detection_status/__init__.py | 3 +- .../detection_status/test_detection_status.py | 2 +- web/tests/functional/diff_local/__init__.py | 3 +- .../functional/diff_local_remote/__init__.py | 3 +- web/tests/functional/diff_remote/__init__.py | 3 +- .../extended_report_data/__init__.py | 3 +- .../func_template/template__init__.py | 3 +- .../functional/instance_manager/__init__.py | 6 +- web/tests/functional/products/__init__.py | 3 +- .../functional/report_viewer_api/__init__.py | 3 +- .../functional/review_status/__init__.py | 3 +- web/tests/functional/run_tag/__init__.py | 3 +- .../server_configuration/__init__.py | 3 +- web/tests/functional/skip/__init__.py | 3 +- .../functional/source_change/__init__.py | 3 +- web/tests/functional/ssl/__init__.py | 3 +- web/tests/functional/statistics/__init__.py | 3 +- .../__init__.py | 3 +- web/tests/functional/suppress/__init__.py | 3 +- web/tests/functional/update/__init__.py | 3 +- web/tests/libtest/codechecker.py | 5 + 57 files changed, 1532 insertions(+), 365 deletions(-) create mode 100644 analyzer/codechecker_analyzer/analyzers/cppcheck/__init__.py create mode 100644 analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py create mode 100644 analyzer/codechecker_analyzer/analyzers/cppcheck/config_handler.py create mode 100644 analyzer/codechecker_analyzer/analyzers/cppcheck/result_handler.py create mode 100644 analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.cpp create mode 100644 analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.noforward.output create mode 100644 analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.output create mode 100644 analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple.cpp create mode 100644 analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple_error.output create mode 100644 analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple_warning.output diff --git a/.github/workflows/install-deps.sh b/.github/workflows/install-deps.sh index f3a8967bbb..0fbfb78a9c 100755 --- a/.github/workflows/install-deps.sh +++ b/.github/workflows/install-deps.sh @@ -14,7 +14,8 @@ sudo apt-get install \ libsasl2-dev \ libssl-dev \ clang-14 \ - clang-tidy-14 + clang-tidy-14 \ + cppcheck sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-14 9999 sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-14 9999 diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 0256b9b827..671fc7c076 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -73,18 +73,19 @@ jobs: - name: "Install run-time dependencies (Linux)" if: ${{ matrix.os == 'ubuntu-18.04' }} run: - sudo apt-get update && sudo apt-get install g++ clang clang-tidy + sudo apt-get update && sudo apt-get install g++ clang clang-tidy cppcheck - name: "Install run-time dependencies (OSX)" if: ${{ matrix.os == 'macos-10.15' }} run: - brew install llvm + brew install llvm cppcheck - name: "Install run-time dependencies (Windows)" if: ${{ matrix.os == 'windows-2019' }} shell: powershell run: | choco install llvm; + choco install --ignore-package-exit-codes cppcheck; echo "C:\Program Files\LLVM\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: "Install pypi package" diff --git a/analyzer/codechecker_analyzer/analysis_manager.py b/analyzer/codechecker_analyzer/analysis_manager.py index 8f02162122..1b301fbad0 100644 --- a/analyzer/codechecker_analyzer/analysis_manager.py +++ b/analyzer/codechecker_analyzer/analysis_manager.py @@ -558,6 +558,8 @@ def __create_timeout(analyzer_process): "after {0} seconds. <<<\n{1}") \ .format(analysis_timeout, rh.analyzer_stderr) + source_analyzer.post_analyze(rh) + # If source file contains escaped spaces ("\ " tokens), then # clangSA writes the plist file with removing this escape # sequence, whereas clang-tidy does not. We rewrite the file @@ -762,6 +764,11 @@ def signal_handler(signum, frame): if not os.path.exists(reproducer_dir) and generate_reproducer: os.makedirs(reproducer_dir) + # Cppcheck raw output directory. + cppcheck_dir = os.path.join(output_path, "cppcheck") + if not os.path.exists(cppcheck_dir): + os.makedirs(cppcheck_dir) + # Collect what other TUs were involved during CTU analysis. ctu_connections_dir = os.path.join(output_path, "ctu_connections") if not os.path.exists(ctu_connections_dir): diff --git a/analyzer/codechecker_analyzer/analyzers/analyzer_base.py b/analyzer/codechecker_analyzer/analyzers/analyzer_base.py index 8ff54cfc1a..ac5f153621 100644 --- a/analyzer/codechecker_analyzer/analyzers/analyzer_base.py +++ b/analyzer/codechecker_analyzer/analyzers/analyzer_base.py @@ -53,6 +53,15 @@ def resolve_missing_binary(cls, configured_binary, environ): """ raise NotImplementedError("Subclasses should implement this!") + @classmethod + def version_compatible(cls, configured_binary, environ): + """ + CodeChecker can only execute certain versions of analyzers. + This function should return True if the analyzer binary is + compatible with the current CodeChecker version. + """ + raise NotImplementedError("Subclasses should implement this!") + @classmethod def construct_config_handler(cls, args, context): """ Should return a subclass of AnalyzerConfigHandler.""" @@ -110,6 +119,12 @@ def get_analyzer_checkers(cls, cfg_handler, environ): """ raise NotImplementedError("Subclasses should implement this!") + def post_analyze(self, result_handler): + """ + Run immediately after the analyze function. + """ + pass + @staticmethod def run_proc(command, env=None, cwd=None, proc_callback=None): """ diff --git a/analyzer/codechecker_analyzer/analyzers/analyzer_types.py b/analyzer/codechecker_analyzer/analyzers/analyzer_types.py index 83289257c7..86cdd683db 100644 --- a/analyzer/codechecker_analyzer/analyzers/analyzer_types.py +++ b/analyzer/codechecker_analyzer/analyzers/analyzer_types.py @@ -22,11 +22,13 @@ from .clangtidy.analyzer import ClangTidy from .clangsa.analyzer import ClangSA +from .cppcheck.analyzer import Cppcheck LOG = get_logger('analyzer') supported_analyzers = {ClangSA.ANALYZER_NAME: ClangSA, - ClangTidy.ANALYZER_NAME: ClangTidy} + ClangTidy.ANALYZER_NAME: ClangTidy, + Cppcheck.ANALYZER_NAME: Cppcheck} def is_ctu_capable(context): @@ -189,8 +191,16 @@ def check_supported_analyzers(analyzers, context): analyzer_bin = found_bin + # Check version compatibility of the analyzer binary. + if analyzer_bin: + analyzer = supported_analyzers[analyzer_name] + if not analyzer.version_compatible(analyzer_bin, check_env): + failed_analyzers.add((analyzer_name, + "Incompatible version.")) + available_analyzer = False + if not analyzer_bin or \ - not host_check.check_clang(analyzer_bin, check_env): + not host_check.check_analyzer(analyzer_bin, check_env): # Analyzers unavailable under absolute paths are deliberately a # configuration problem. failed_analyzers.add((analyzer_name, diff --git a/analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py b/analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py index a1df95b232..bd779f5f93 100644 --- a/analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py +++ b/analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py @@ -412,6 +412,13 @@ def resolve_missing_binary(cls, configured_binary, environ): LOG.debug("Using '%s' for ClangSA!", clang) return clang + @classmethod + def version_compatible(cls, configured_binary, environ): + """ + Check the version compatibility of the given analyzer binary. + """ + return True + def construct_result_handler(self, buildaction, report_output, checker_labels, skiplist_handler): """ diff --git a/analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py b/analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py index 6d2b9130eb..20f1664f21 100644 --- a/analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py +++ b/analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py @@ -319,6 +319,13 @@ def resolve_missing_binary(cls, configured_binary, environ): LOG.debug("Using '%s' for Clang-tidy!", clangtidy) return clangtidy + @classmethod + def version_compatible(cls, configured_binary, environ): + """ + Check the version compatibility of the given analyzer binary. + """ + return True + def construct_result_handler(self, buildaction, report_output, checker_labels, skiplist_handler): """ diff --git a/analyzer/codechecker_analyzer/analyzers/cppcheck/__init__.py b/analyzer/codechecker_analyzer/analyzers/cppcheck/__init__.py new file mode 100644 index 0000000000..4259749345 --- /dev/null +++ b/analyzer/codechecker_analyzer/analyzers/cppcheck/__init__.py @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------- +# +# Part of the CodeChecker project, under the Apache License v2.0 with +# LLVM Exceptions. See LICENSE for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ------------------------------------------------------------------------- diff --git a/analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py b/analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py new file mode 100644 index 0000000000..c9018aa82c --- /dev/null +++ b/analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py @@ -0,0 +1,357 @@ +# ------------------------------------------------------------------------- +# +# Part of the CodeChecker project, under the Apache License v2.0 with +# LLVM Exceptions. See LICENSE for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ------------------------------------------------------------------------- +""" +""" +# TODO distutils will be removed in python3.12 +from distutils.version import StrictVersion +from pathlib import Path +import os +import re +import shlex +import shutil +import subprocess +import xml.etree.ElementTree as ET + +from codechecker_common.logger import get_logger + +from codechecker_analyzer.env import extend, get_binary_in_path + +from .. import analyzer_base + +from .config_handler import CppcheckConfigHandler +from .result_handler import CppcheckResultHandler + +from ..config_handler import CheckerState + +LOG = get_logger('analyzer.cppcheck') + + +def parse_checkers(cppcheck_output): + """ + Parse cppcheck checkers list given by '--errorlist' flag. Return a list of + (checker_name, description) pairs. + """ + checkers = [] + + tree = ET.ElementTree(ET.fromstring(cppcheck_output)) + root = tree.getroot() + errors = root.find('errors') + for error in errors.findall('error'): + name = error.attrib.get('id') + if name: + name = "cppcheck-" + name + msg = str(error.attrib.get('msg') or '') + # TODO: Check severity handling in cppcheck + # severity = error.attrib.get('severity') + + # checkers.append((name, msg, severity)) + checkers.append((name, msg)) + + return checkers + + +def parse_version(cppcheck_output): + """ + Parse cppcheck version output and return the version number. + """ + version_re = re.compile(r'^Cppcheck (?P[\d\.]+)') + match = version_re.match(cppcheck_output) + if match: + return StrictVersion(match.group('version')) + + +class Cppcheck(analyzer_base.SourceAnalyzer): + """ + Constructs the Cppcheck analyzer commands. + """ + + ANALYZER_NAME = 'cppcheck' + + def add_checker_config(self, checker_cfg): + LOG.error("Checker configuration for Cppcheck is not implemented yet") + + def get_analyzer_mentioned_files(self, output): + """ + Return a collection of files that were mentioned by the analyzer in + its standard outputs, which should be analyzer_stdout or + analyzer_stderr from a result handler. + """ + pass + + def construct_analyzer_cmd(self, result_handler): + """ + Construct analyzer command for cppcheck. + """ + try: + config = self.config_handler + + analyzer_cmd = [config.analyzer_binary] + + # TODO implement a more granular commandline checker config + # Cppcheck runs with all checkers enabled for the time being + # the unneded checkers are passed as suppressed checkers + analyzer_cmd.append('--enable=all') + + for checker_name, value in config.checks().items(): + if value[0] == CheckerState.disabled: + # TODO python3.9 removeprefix method would be nicer + # than startswith and a hardcoded slicing + if checker_name.startswith("cppcheck-"): + checker_name = checker_name[9:] + analyzer_cmd.append('--suppress=' + checker_name) + + # unusedFunction check is for whole program analysis, + # which is not compatible with per source file analysis. + analyzer_cmd.append('--suppress=unusedFunction') + + # Add extra arguments. + analyzer_cmd.extend(config.analyzer_extra_arguments) + + # Pass includes, and macro (un)definitions + for analyzer_option in self.buildaction.analyzer_options: + if analyzer_option.startswith("-I") or \ + analyzer_option.startswith("-U") or \ + analyzer_option.startswith("-D"): + analyzer_cmd.extend([analyzer_option]) + elif analyzer_option.startswith("-i"): + analyzer_cmd.extend(["-I" + analyzer_option[2:]]) + elif analyzer_option.startswith("-std"): + standard = analyzer_option.split("=")[-1] \ + .lower().replace("gnu", "c") + analyzer_cmd.extend(["--std=" + standard]) + + # TODO fix this in a follow up patch, because it is failing + # the macos pypy test. + # analyzer_cmd.extend(["--std=" + + # self.buildaction.compiler_standard + # .split("=")[-1].lower().replace("gnu", "c")]) + + # By default there is no platform configuration, + # but a platform definition xml can be specified. + if 'platform' in config.analyzer_config: + analyzer_cmd.append( + "--platform=" + config.analyzer_config['platform'][0]) + else: + analyzer_cmd.append("--platform=native") + + if 'addons' in config.analyzer_config: + for addon in config.analyzer_config["addons"]: + analyzer_cmd.extend( + ["--addon=" + str(Path(addon).absolute())]) + + if 'libraries' in config.analyzer_config: + for lib in config.analyzer_config["libraries"]: + analyzer_cmd.extend( + ["--library=" + str(Path(lib).absolute())]) + + # TODO Suggest a better place for this + # cppcheck wont create the output folders for itself + output_dir = Path(result_handler.workspace, "cppcheck", + result_handler.buildaction_hash) + output_dir.mkdir(exist_ok=True) + + analyzer_cmd.append('--plist-output=' + str(output_dir)) + + analyzer_cmd.append(self.source_file) + + return analyzer_cmd + + except Exception as ex: + LOG.error(ex) + return [] + + @classmethod + def get_analyzer_checkers( + cls, + cfg_handler: CppcheckConfigHandler, + env): + """ + Return the list of the supported checkers. + """ + command = [cfg_handler.analyzer_binary, "--errorlist"] + + try: + result = subprocess.check_output(command, env=env) + return parse_checkers(result) + except (subprocess.CalledProcessError) as e: + LOG.error(e.stderr) + except (OSError) as e: + LOG.error(e.errno) + return [] + + @classmethod + def get_analyzer_config(cls, cfg_handler, environ): + """ + Config options for cppcheck. + """ + return [("addons", "A list of cppcheck addon files."), + ("libraries", "A list of cppcheck library definiton files."), + ("platform", "The platform configuration .xml file.") + ] + + @classmethod + def get_checker_config(cls, cfg_handler, environ): + """ + TODO add config options for cppcheck checkers. + """ + return [] + + def post_analyze(self, result_handler): + """ + Post process the reuslts after the analysis. + Will copy the plist files created by cppcheck into the + root of the reports folder. + Renames the source plist files to *.plist.bak because + The report parsing of the Parse command is done recursively. + + """ + # Cppcheck can generate an id into the output plist file name + # we get "the" *.plist file from the unique output folder + + cppcheck_out_folder = Path(result_handler.workspace, + "cppcheck", + result_handler.buildaction_hash) + cppcheck_outs = cppcheck_out_folder.glob('**/*.plist') + + for cppcheck_out in list(cppcheck_outs): + codechecker_out = os.path.join(result_handler.workspace, + result_handler.analyzer_result_file) + + # plists generated by cppcheck are still "parsable" by our plist + # parser. Renaming is needed to circumvent the processing of the + # raw files. + try: + shutil.copy2(cppcheck_out, codechecker_out) + Path(cppcheck_out).rename(str(cppcheck_out) + ".bak") + except(OSError) as e: + LOG.error(e.errno) + + @classmethod + def resolve_missing_binary(cls, configured_binary, env): + """ + In case of the configured binary for the analyzer is not found in the + PATH, this method is used to find a callable binary. + """ + + LOG.debug("%s not found in path for Cppcheck!", configured_binary) + + if os.path.isabs(configured_binary): + # Do not autoresolve if the path is an absolute path as there + # is nothing we could auto-resolve that way. + return False + + cppcheck = get_binary_in_path(['cppcheck'], + r'^cppcheck(-\d+(\.\d+){0,2})?$', + env) + + if cppcheck: + LOG.debug("Using '%s' for Cppcheck!", cppcheck) + return cppcheck + + @classmethod + def __get_analyzer_version(cls, analyzer_binary, env): + """ + Return the analyzer version. + """ + command = [analyzer_binary, "--version"] + + try: + command = shlex.split(' '.join(command)) + result = subprocess.check_output( + command, + env=env, + encoding="utf-8", + errors="ignore") + return parse_version(result) + except (subprocess.CalledProcessError, OSError): + return [] + + @classmethod + def version_compatible(cls, configured_binary, environ): + """ + Check the version compatibility of the given analyzer binary. + """ + analyzer_version = \ + cls.__get_analyzer_version(configured_binary, environ) + + # The analyzer version should be above 1.80 because '--plist-output' + # argument was introduced in this release. + if analyzer_version >= StrictVersion("1.80"): + return True + + return False + + def construct_result_handler(self, buildaction, report_output, + checker_labels, skiplist_handler): + """ + See base class for docs. + """ + res_handler = CppcheckResultHandler(buildaction, report_output, + self.config_handler.report_hash) + + res_handler.checker_labels = checker_labels + res_handler.skiplist_handler = skiplist_handler + + return res_handler + + @classmethod + def construct_config_handler(cls, args, context): + handler = CppcheckConfigHandler() + handler.analyzer_binary = context.analyzer_binaries.get( + cls.ANALYZER_NAME) + + analyzer_config = {} + + if 'analyzer_config' in args and \ + isinstance(args.analyzer_config, list): + r = re.compile(r'(?P.+?):(?P.+?)=(?P.+)') + for cfg in args.analyzer_config: + m = re.search(r, cfg) + if m.group('analyzer') == cls.ANALYZER_NAME: + key = m.group('key') + if key not in analyzer_config: + analyzer_config[key] = [] + analyzer_config[m.group('key')].append(m.group('value')) + + handler.analyzer_config = analyzer_config + + check_env = extend(context.path_env_extra, + context.ld_lib_path_extra) + + # Overwrite PATH to contain only the parent of the cppcheck binary. + if os.path.isabs(handler.analyzer_binary): + check_env['PATH'] = os.path.dirname(handler.analyzer_binary) + + checkers = cls.get_analyzer_checkers(handler, check_env) + + # Cppcheck can and will report with checks that have a different + # name than marked in the --errorlist xml. To be able to suppress + # these reports, the checkerlist needs to be extended by those found + # in the label file. + checker_labels = context.checker_labels + checkers_from_label = checker_labels.checkers("cppcheck") + parsed_set = set([data[0] for data in checkers]) + for checker in set(checkers_from_label): + if checker not in parsed_set: + checkers.append((checker, "")) + + try: + cmdline_checkers = args.ordered_checkers + except AttributeError: + LOG.debug_analyzer('No checkers were defined in ' + 'the command line for %s', + cls.ANALYZER_NAME) + cmdline_checkers = [] + + handler.initialize_checkers( + context, + checkers, + cmdline_checkers, + 'enable_all' in args and args.enable_all) + + return handler diff --git a/analyzer/codechecker_analyzer/analyzers/cppcheck/config_handler.py b/analyzer/codechecker_analyzer/analyzers/cppcheck/config_handler.py new file mode 100644 index 0000000000..8508ea2fb0 --- /dev/null +++ b/analyzer/codechecker_analyzer/analyzers/cppcheck/config_handler.py @@ -0,0 +1,43 @@ +# ------------------------------------------------------------------------- +# +# Part of the CodeChecker project, under the Apache License v2.0 with +# LLVM Exceptions. See LICENSE for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ------------------------------------------------------------------------- +""" +Config handler for Cppcheck analyzer. +""" +from .. import config_handler +from ..config_handler import CheckerState + + +class CppcheckConfigHandler(config_handler.AnalyzerConfigHandler): + """ + Configuration handler for Cppcheck analyzer. + """ + def initialize_checkers(self, + analyzer_context, + checkers, + cmdline_enable=None, + enable_all=False): + if not cmdline_enable: + cmdline_enable = list() + """ + Set all the default checkers to disabled. This will ensure that + --enable=all will not run with all the possible checkers + """ + super().initialize_checkers( + analyzer_context, + checkers, + cmdline_enable, + enable_all) + + # Set all the checkers with default CheckerState checkers to + # disabled. This will ensure that --enable=all will not run with + # all the possible checkers. All the checkers that are in the default + # profile (or configured othewise, eg.: from the cli) should be + # already enabled at this point. + for checker_name, data in self.checks().items(): + if data[0] == CheckerState.default: + self.set_checker_enabled(checker_name, enabled=False) diff --git a/analyzer/codechecker_analyzer/analyzers/cppcheck/result_handler.py b/analyzer/codechecker_analyzer/analyzers/cppcheck/result_handler.py new file mode 100644 index 0000000000..b996349075 --- /dev/null +++ b/analyzer/codechecker_analyzer/analyzers/cppcheck/result_handler.py @@ -0,0 +1,77 @@ +# ------------------------------------------------------------------------- +# +# Part of the CodeChecker project, under the Apache License v2.0 with +# LLVM Exceptions. See LICENSE for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ------------------------------------------------------------------------- +""" +Result handler for Cppcheck. +""" +from typing import Optional + +from codechecker_report_converter.report.parser.base import AnalyzerInfo +from codechecker_report_converter.analyzers.cppcheck.analyzer_result import \ + AnalyzerResult +from codechecker_report_converter.report import BugPathEvent, \ + Range, report_file +from codechecker_report_converter.report.hash import get_report_hash, HashType + +from codechecker_common.logger import get_logger +from codechecker_common.skiplist_handler import SkipListHandlers + +from ..result_handler_base import ResultHandler + +LOG = get_logger('analyzer.cppcheck') + + +class CppcheckResultHandler(ResultHandler): + """ + Create analyzer result file for Cppcheck output. + """ + + def __init__(self, *args, **kwargs): + self.analyzer_info = AnalyzerInfo(name=AnalyzerResult.TOOL_NAME) + + super(CppcheckResultHandler, self).__init__(*args, **kwargs) + + def postprocess_result(self, skip_handlers: Optional[SkipListHandlers]): + """ + Generate analyzer result output file which can be parsed and stored + into the database. + """ + LOG.debug_analyzer(self.analyzer_stdout) + + reports = report_file.get_reports( + self.analyzer_result_file, self.checker_labels, + source_dir_path=self.source_dir_path) + + reports = [r for r in reports if not r.skip(skip_handlers)] + for report in reports: + # TODO check if prefix cascading still occurs. + if not report.checker_name.startswith("cppcheck-"): + report.checker_name = "cppcheck-" + report.checker_name + + hash_type = HashType.PATH_SENSITIVE + if self.report_hash_type == 'context-free-v2': + hash_type = HashType.CONTEXT_FREE + elif self.report_hash_type == 'diagnostic-message': + hash_type = HashType.DIAGNOSTIC_MESSAGE + + for report in reports: + report.report_hash = get_report_hash(report, hash_type) + bpe = BugPathEvent( + report.message, + report.file, + report.line, + report.column, + Range(report.line, + report.column, + report.line, + report.column)) + if bpe != report.bug_path_events[-1]: + report.bug_path_events.append(bpe) + + report_file.create( + self.analyzer_result_file, reports, self.checker_labels, + self.analyzer_info) diff --git a/analyzer/codechecker_analyzer/analyzers/result_handler_base.py b/analyzer/codechecker_analyzer/analyzers/result_handler_base.py index c0447238d5..2f0997504d 100644 --- a/analyzer/codechecker_analyzer/analyzers/result_handler_base.py +++ b/analyzer/codechecker_analyzer/analyzers/result_handler_base.py @@ -59,6 +59,7 @@ def __init__(self, action, workspace, report_hash_type=None): self.skiplist_handler = None self.analyzed_source_file = None self.analyzer_returncode = 1 + self.buildaction_hash = '' self.__buildaction = action self.__result_file = None @@ -133,9 +134,12 @@ def analyzer_action_str(self): build_info = source_file + '_' + ' '.join(args) + self.buildaction_hash = \ + hashlib.md5(build_info.encode(errors='ignore')).hexdigest() + return analyzed_file_name + '_' + \ str(self.buildaction.analyzer_type) + '_' + \ - hashlib.md5(build_info.encode(errors='ignore')).hexdigest() + self.buildaction_hash @property def analyzer_result_file(self): diff --git a/analyzer/codechecker_analyzer/cmd/analyzers.py b/analyzer/codechecker_analyzer/cmd/analyzers.py index 5e0f900736..2fac4b7a96 100644 --- a/analyzer/codechecker_analyzer/cmd/analyzers.py +++ b/analyzer/codechecker_analyzer/cmd/analyzers.py @@ -146,6 +146,9 @@ def main(args): LOG.warning("'--dump-config clangsa' is not supported yet. " "Please make sure that you are using Clang 9 or " "newer.") + elif args.dump_config == 'cppcheck': + # TODO: Not supported by CppCheck yet! + LOG.warning("'--dump-config cppcheck' is not supported.") return diff --git a/analyzer/codechecker_analyzer/cmd/checkers.py b/analyzer/codechecker_analyzer/cmd/checkers.py index d503c2573a..9af763d576 100644 --- a/analyzer/codechecker_analyzer/cmd/checkers.py +++ b/analyzer/codechecker_analyzer/cmd/checkers.py @@ -672,8 +672,10 @@ def __print_checker_config(args: argparse.Namespace): configs = analyzer_class.get_checker_config(config_handler, analyzer_environment) if not configs: - analyzer_failures.append(analyzer) - continue + # Checker configurations are not supported by cppcheck + if analyzer != "cppcheck": + analyzer_failures.append(analyzer) + continue rows.extend((':'.join((analyzer, c[0])), c[1]) if 'details' in args else (':'.join((analyzer, c[0])),) for c in configs) diff --git a/analyzer/codechecker_analyzer/host_check.py b/analyzer/codechecker_analyzer/host_check.py index 9fd32721a2..5b7fe5f7dd 100644 --- a/analyzer/codechecker_analyzer/host_check.py +++ b/analyzer/codechecker_analyzer/host_check.py @@ -20,7 +20,7 @@ LOG = get_logger('analyzer') -def check_clang(compiler_bin, env): +def check_analyzer(compiler_bin, env): """ Simple check if clang is available. """ diff --git a/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py b/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py index 8dbf179ff3..e8a06efa5d 100644 --- a/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py +++ b/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py @@ -210,7 +210,8 @@ def check_one_file(self, path, mode): # analysis. "[] - Enabled checkers:", "clang-tidy:", - "clangsa:"] + "clangsa:", + "cppcheck:"] for line in output: # replace timestamps line = re.sub(r'\[\w+ \d{4}-\d{2}-\d{2} \d{2}:\d{2}\]', diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/Makefile b/analyzer/tests/functional/analyze_and_parse/test_files/Makefile index 479e62649f..fdccbdf52e 100644 --- a/analyzer/tests/functional/analyze_and_parse/test_files/Makefile +++ b/analyzer/tests/functional/analyze_and_parse/test_files/Makefile @@ -39,3 +39,9 @@ collision: $(CXX) -w filename_collision/main.cpp filename_collision/a/f.cpp filename_collision/b/f.cpp -o /dev/null tidy_alias: $(CXX) -w tidy_alias.cpp -o /dev/null +cppcheck_multiple: + $(CXX) -w cppcheck_multiple.cpp -o /dev/null +cppcheck_args: + $(CXX) -w cppcheck_args.cpp -o /dev/null +cppcheck_undef_args: + $(CXX) -w cppcheck_args.cpp -UHAVE_NULL_DEREFERENCE -o /dev/null diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.cpp b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.cpp new file mode 100644 index 0000000000..c6cc4d12ff --- /dev/null +++ b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.cpp @@ -0,0 +1,12 @@ +int main() +{ + +#ifdef HAVE_NULL_DEREFERENCE + int *ptr = nullptr; +#else + int x = 0; + int *ptr = &x; +#endif + + return *ptr; +} diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.noforward.output b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.noforward.output new file mode 100644 index 0000000000..2e31eb4fa7 --- /dev/null +++ b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.noforward.output @@ -0,0 +1,57 @@ +NORMAL#CodeChecker log --output $LOGFILE$ --build "make cppcheck_args" --quiet +NORMAL#CodeChecker analyze $LOGFILE$ --output $OUTPUT$ --analyzers cppcheck +NORMAL#CodeChecker parse $OUTPUT$ +CHECK#CodeChecker check --build "make cppcheck_args" --output $OUTPUT$ --quiet --analyzers cppcheck +----------------------------------------------- +[] - Starting build... +[] - Using CodeChecker ld-logger. +[] - Build finished successfully. +[] - Starting static analysis ... +[] - [1/1] cppcheck analyzed cppcheck_args.cpp successfully. +[] - ----==== Summary ====---- +[] - Successfully analyzed +[] - cppcheck: 1 +[] - Total analyzed compilation commands: 1 +[] - ----=================---- +[] - Analysis finished. +[] - To view results in the terminal use the "CodeChecker parse" command. +[] - To store results use the "CodeChecker store" command. +[] - See --help and the user guide for further options about parsing and storing the reports. +[] - ----=================---- +[HIGH] cppcheck_args.cpp:11:11: Null pointer dereference: ptr [cppcheck-nullPointer] + return *ptr; + ^ + +Found 1 defect(s) in cppcheck_args.cpp + + +----==== Severity Statistics ====---- +---------------------------- +Severity | Number of reports +---------------------------- +HIGH | 1 +---------------------------- +----=================---- + +----==== Checker Statistics ====---- +--------------------------------------------------- +Checker name | Severity | Number of reports +--------------------------------------------------- +cppcheck-nullPointer | HIGH | 1 +--------------------------------------------------- +----=================---- + +----==== File Statistics ====---- +------------------------------------- +File name | Number of reports +------------------------------------- +cppcheck_args.cpp | 1 +------------------------------------- +----=================---- + +----======== Summary ========---- +--------------------------------------------- +Number of processed analyzer result files | 1 +Number of analyzer reports | 1 +--------------------------------------------- +----=================---- diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.output b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.output new file mode 100644 index 0000000000..46c2a8d717 --- /dev/null +++ b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_args.output @@ -0,0 +1,28 @@ +NORMAL#CodeChecker log --output $LOGFILE$ --build "make cppcheck_undef_args" --quiet +NORMAL#CodeChecker analyze $LOGFILE$ --output $OUTPUT$ --analyzers cppcheck +NORMAL#CodeChecker parse $OUTPUT$ +CHECK#CodeChecker check --build "make cppcheck_undef_args" --output $OUTPUT$ --quiet --analyzers cppcheck +----------------------------------------------- +[] - Starting build... +[] - Using CodeChecker ld-logger. +[] - Build finished successfully. +[] - Starting static analysis ... +[] - [1/1] cppcheck analyzed cppcheck_args.cpp successfully. +[] - ----==== Summary ====---- +[] - Successfully analyzed +[] - cppcheck: 1 +[] - Total analyzed compilation commands: 1 +[] - ----=================---- +[] - Analysis finished. +[] - To view results in the terminal use the "CodeChecker parse" command. +[] - To store results use the "CodeChecker store" command. +[] - See --help and the user guide for further options about parsing and storing the reports. +[] - ----=================---- +Found no defects in cppcheck_args.cpp + +----======== Summary ========---- +--------------------------------------------- +Number of processed analyzer result files | 1 +Number of analyzer reports | 0 +--------------------------------------------- +----=================---- diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple.cpp b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple.cpp new file mode 100644 index 0000000000..65c79c8d29 --- /dev/null +++ b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple.cpp @@ -0,0 +1,16 @@ +int error() +{ + int i; + return i; +} + +bool warning(int param) +{ + return param > 3 && param < 4; +} + +int main() +{ + return 0; +} + diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple_error.output b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple_error.output new file mode 100644 index 0000000000..046cbc1a78 --- /dev/null +++ b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple_error.output @@ -0,0 +1,57 @@ +NORMAL#CodeChecker log --output $LOGFILE$ --build "make cppcheck_multiple" --quiet +NORMAL#CodeChecker analyze $LOGFILE$ --output $OUTPUT$ --analyzers cppcheck -d cppcheck-incorrectLogicOperator +NORMAL#CodeChecker parse $OUTPUT$ +CHECK#CodeChecker check --build "make cppcheck_multiple" --output $OUTPUT$ --quiet --analyzers cppcheck -d cppcheck-incorrectLogicOperator +----------------------------------------------- +[] - Starting build... +[] - Using CodeChecker ld-logger. +[] - Build finished successfully. +[] - Starting static analysis ... +[] - [1/1] cppcheck analyzed cppcheck_multiple.cpp successfully. +[] - ----==== Summary ====---- +[] - Successfully analyzed +[] - cppcheck: 1 +[] - Total analyzed compilation commands: 1 +[] - ----=================---- +[] - Analysis finished. +[] - To view results in the terminal use the "CodeChecker parse" command. +[] - To store results use the "CodeChecker store" command. +[] - See --help and the user guide for further options about parsing and storing the reports. +[] - ----=================---- +[HIGH] cppcheck_multiple.cpp:4:10: Uninitialized variable: i [cppcheck-uninitvar] + return i; + ^ + +Found 1 defect(s) in cppcheck_multiple.cpp + + +----==== Severity Statistics ====---- +---------------------------- +Severity | Number of reports +---------------------------- +HIGH | 1 +---------------------------- +----=================---- + +----==== Checker Statistics ====---- +------------------------------------------------- +Checker name | Severity | Number of reports +------------------------------------------------- +cppcheck-uninitvar | HIGH | 1 +------------------------------------------------- +----=================---- + +----==== File Statistics ====---- +----------------------------------------- +File name | Number of reports +----------------------------------------- +cppcheck_multiple.cpp | 1 +----------------------------------------- +----=================---- + +----======== Summary ========---- +--------------------------------------------- +Number of processed analyzer result files | 1 +Number of analyzer reports | 1 +--------------------------------------------- +----=================---- diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple_warning.output b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple_warning.output new file mode 100644 index 0000000000..38d2728f0e --- /dev/null +++ b/analyzer/tests/functional/analyze_and_parse/test_files/cppcheck_multiple_warning.output @@ -0,0 +1,57 @@ +NORMAL#CodeChecker log --output $LOGFILE$ --build "make cppcheck_multiple" --quiet +NORMAL#CodeChecker analyze $LOGFILE$ --output $OUTPUT$ --analyzers cppcheck -d cppcheck-uninitvar +NORMAL#CodeChecker parse $OUTPUT$ +CHECK#CodeChecker check --build "make cppcheck_multiple" --output $OUTPUT$ --quiet --analyzers cppcheck -d cppcheck-uninitvar +----------------------------------------------- +[] - Starting build... +[] - Using CodeChecker ld-logger. +[] - Build finished successfully. +[] - Starting static analysis ... +[] - [1/1] cppcheck analyzed cppcheck_multiple.cpp successfully. +[] - ----==== Summary ====---- +[] - Successfully analyzed +[] - cppcheck: 1 +[] - Total analyzed compilation commands: 1 +[] - ----=================---- +[] - Analysis finished. +[] - To view results in the terminal use the "CodeChecker parse" command. +[] - To store results use the "CodeChecker store" command. +[] - See --help and the user guide for further options about parsing and storing the reports. +[] - ----=================---- +[MEDIUM] cppcheck_multiple.cpp:9:20: Logical conjunction always evaluates to false: param > 3 && param < 4. [cppcheck-incorrectLogicOperator] + return param > 3 && param < 4; + ^ + +Found 1 defect(s) in cppcheck_multiple.cpp + + +----==== Severity Statistics ====---- +---------------------------- +Severity | Number of reports +---------------------------- +MEDIUM | 1 +---------------------------- +----=================---- + +----==== Checker Statistics ====---- +-------------------------------------------------------------- +Checker name | Severity | Number of reports +-------------------------------------------------------------- +cppcheck-incorrectLogicOperator | MEDIUM | 1 +-------------------------------------------------------------- +----=================---- + +----==== File Statistics ====---- +----------------------------------------- +File name | Number of reports +----------------------------------------- +cppcheck_multiple.cpp | 1 +----------------------------------------- +----=================---- + +----======== Summary ========---- +--------------------------------------------- +Number of processed analyzer result files | 1 +Number of analyzer reports | 1 +--------------------------------------------- +----=================---- diff --git a/analyzer/tests/functional/ctu_failure/test_ctu_failure.py b/analyzer/tests/functional/ctu_failure/test_ctu_failure.py index e9a81d6609..721134a2f2 100644 --- a/analyzer/tests/functional/ctu_failure/test_ctu_failure.py +++ b/analyzer/tests/functional/ctu_failure/test_ctu_failure.py @@ -404,7 +404,7 @@ def __getClangSaPath(self): env=self.env) self.assertEqual(result, 0, "Failed to run analyzer.") json_data = json.loads(output) - if json_data[0]["name"] == "clangsa": - return json_data[0]["path"] - if json_data[1]["name"] == "clangsa": - return json_data[1]["path"] + + for i in range(len(json_data)): + if json_data[i]["name"] == "clangsa": + return json_data[i]["path"] diff --git a/config/labels/analyzers/cppcheck.json b/config/labels/analyzers/cppcheck.json index 73c71006be..b880ead1d6 100644 --- a/config/labels/analyzers/cppcheck.json +++ b/config/labels/analyzers/cppcheck.json @@ -1,898 +1,1149 @@ { "analyzer": "cppcheck", + "analyzer_version": "2.9", "labels": { - "AssignmentAddressToInteger": [ + "cppcheck-AssignmentAddressToInteger": [ "severity:LOW" ], - "AssignmentIntegerToAddress": [ + "cppcheck-AssignmentIntegerToAddress": [ "severity:LOW" ], - "CastAddressToIntegerAtReturn": [ + "cppcheck-CastAddressToIntegerAtReturn": [ "severity:LOW" ], - "CastIntegerToAddressAtReturn": [ + "cppcheck-CastIntegerToAddressAtReturn": [ "severity:LOW" ], - "ConfigurationNotChecked": [ + "cppcheck-ConfigurationNotChecked": [ "severity:LOW" ], - "IOWithoutPositioning": [ + "cppcheck-IOWithoutPositioning": [ + "profile:default", "severity:HIGH" ], - "StlMissingComparison": [ + "cppcheck-StlMissingComparison": [ + "profile:default", "severity:MEDIUM" ], - "accessForwarded": [ + "cppcheck-accessForwarded": [ + "profile:default", "severity:MEDIUM" ], - "accessMoved": [ + "cppcheck-accessMoved": [ + "profile:default", "severity:MEDIUM" ], - "arithOperationsOnVoidPointer": [ + "cppcheck-argumentSize": [ + "profile:default", + "severity:MEDIUM" + ], + "cppcheck-arithOperationsOnVoidPointer": [ "severity:LOW" ], - "arrayIndexOutOfBounds": [ + "cppcheck-arrayIndexOutOfBounds": [ + "profile:default", "severity:HIGH" ], - "arrayIndexOutOfBoundsCond": [ + "cppcheck-arrayIndexOutOfBoundsCond": [ + "profile:default", "severity:MEDIUM" ], - "arrayIndexThenCheck": [ + "cppcheck-arrayIndexThenCheck": [ "severity:STYLE" ], - "assertWithSideEffect": [ + "cppcheck-assertWithSideEffect": [ + "profile:default", "severity:MEDIUM" ], - "assignBoolToFloat": [ + "cppcheck-assignBoolToFloat": [ "severity:STYLE" ], - "assignBoolToPointer": [ + "cppcheck-assignBoolToPointer": [ + "profile:default", "severity:HIGH" ], - "assignIfError": [ + "cppcheck-assignIfError": [ "severity:STYLE" ], - "assignmentInAssert": [ + "cppcheck-assignmentInAssert": [ + "profile:default", "severity:MEDIUM" ], - "autoVariables": [ + "cppcheck-assignmentInCondition": [ + "severity:LOW" + ], + "cppcheck-autoVariables": [ + "profile:default", "severity:HIGH" ], - "autovarInvalidDeallocation": [ + "cppcheck-autovarInvalidDeallocation": [ + "profile:default", "severity:HIGH" ], - "badBitmaskCheck": [ + "cppcheck-badBitmaskCheck": [ + "profile:default", "severity:MEDIUM" ], - "bitwiseOnBoolean": [ + "cppcheck-bitwiseOnBoolean": [ "severity:STYLE" ], - "boostForeachError": [ + "cppcheck-boostForeachError": [ + "profile:default", "severity:HIGH" ], - "bufferAccessOutOfBounds": [ + "cppcheck-bufferAccessOutOfBounds": [ + "profile:default", "severity:HIGH" ], - "catchExceptionByValue": [ + "cppcheck-catchExceptionByValue": [ "severity:STYLE" ], - "charBitOp": [ + "cppcheck-charBitOp": [ + "profile:default", "severity:MEDIUM" ], - "charLiteralWithCharPtrCompare": [ + "cppcheck-charLiteralWithCharPtrCompare": [ + "profile:default", "severity:MEDIUM" ], - "checkCastIntToCharAndBack": [ + "cppcheck-checkCastIntToCharAndBack": [ + "profile:default", "severity:MEDIUM" ], - "clarifyCalculation": [ + "cppcheck-clarifyCalculation": [ "severity:STYLE" ], - "clarifyCondition": [ + "cppcheck-clarifyCondition": [ "severity:STYLE" ], - "clarifyStatement": [ + "cppcheck-clarifyStatement": [ + "profile:default", "severity:MEDIUM" ], - "commaSeparatedReturn": [ + "cppcheck-commaSeparatedReturn": [ "severity:STYLE" ], - "compareBoolExpressionWithInt": [ + "cppcheck-compareBoolExpressionWithInt": [ + "profile:default", "severity:MEDIUM" ], - "comparePointers": [ + "cppcheck-comparePointers": [ + "profile:default", "severity:HIGH" ], - "comparisonError": [ + "cppcheck-compareValueOutOfTypeRangeError": [ + "severity:LOW" + ], + "cppcheck-comparisonError": [ "severity:STYLE" ], - "comparisonFunctionIsAlwaysTrueOrFalse": [ + "cppcheck-comparisonFunctionIsAlwaysTrueOrFalse": [ + "profile:default", "severity:MEDIUM" ], - "comparisonOfBoolWithBoolError": [ + "cppcheck-comparisonOfBoolWithBoolError": [ "severity:STYLE" ], - "comparisonOfBoolWithInvalidComparator": [ + "cppcheck-comparisonOfBoolWithInvalidComparator": [ + "profile:default", "severity:MEDIUM" ], - "comparisonOfFuncReturningBoolError": [ + "cppcheck-comparisonOfFuncReturningBoolError": [ "severity:STYLE" ], - "comparisonOfTwoFuncsReturningBoolError": [ + "cppcheck-comparisonOfTwoFuncsReturningBoolError": [ "severity:STYLE" ], - "constStatement": [ + "cppcheck-constParameter": [ + "severity:LOW" + ], + "cppcheck-constParameterCallback": [ + "severity:LOW" + ], + "cppcheck-constStatement": [ + "profile:default", "severity:MEDIUM" ], - "constVariable": [ + "cppcheck-constVariable": [ "severity:STYLE" ], - "containerOutOfBounds": [ + "cppcheck-containerOutOfBounds": [ + "profile:default", "severity:HIGH" ], - "copyCtorAndEqOperator": [ + "cppcheck-copyCtorAndEqOperator": [ + "profile:default", "severity:MEDIUM" ], - "copyCtorPointerCopying": [ + "cppcheck-copyCtorPointerCopying": [ + "profile:default", "severity:MEDIUM" ], - "coutCerrMisusage": [ + "cppcheck-coutCerrMisusage": [ + "profile:default", "severity:HIGH" ], - "cstyleCast": [ + "cppcheck-cstyleCast": [ "severity:STYLE" ], - "danglingLifetime": [ + "cppcheck-danglingLifetime": [ + "profile:default", "severity:HIGH" ], - "danglingReference": [ + "cppcheck-danglingReference": [ + "profile:default", "severity:HIGH" ], - "danglingTempReference": [ + "cppcheck-danglingTempReference": [ "severity:HIGH" ], - "danglingTemporaryLifetime": [ + "cppcheck-danglingTemporaryLifetime": [ + "profile:default", "severity:HIGH" ], - "deallocDealloc": [ + "cppcheck-deallocDealloc": [ + "profile:default", "severity:HIGH" ], - "deallocret": [ + "cppcheck-deallocret": [ + "profile:default", "severity:HIGH" ], - "deallocuse": [ + "cppcheck-deallocuse": [ + "profile:default", "severity:HIGH" ], - "derefInvalidIterator": [ + "cppcheck-derefInvalidIterator": [ + "profile:default", "severity:MEDIUM" ], - "divideSizeof": [ + "cppcheck-divideSizeof": [ + "profile:default", "severity:MEDIUM" ], - "doubleFree": [ + "cppcheck-doubleFree": [ + "profile:default", "severity:HIGH" ], - "duplInheritedMember": [ + "cppcheck-duplInheritedMember": [ + "profile:default", "severity:MEDIUM" ], - "duplicateAssignExpression": [ + "cppcheck-duplicateAssignExpression": [ "severity:STYLE" ], - "duplicateBranch": [ + "cppcheck-duplicateBranch": [ "severity:STYLE" ], - "duplicateBreak": [ + "cppcheck-duplicateBreak": [ "severity:STYLE" ], - "duplicateCondition": [ + "cppcheck-duplicateCondition": [ "severity:STYLE" ], - "duplicateConditionalAssign": [ + "cppcheck-duplicateConditionalAssign": [ "severity:STYLE" ], - "duplicateExpression": [ + "cppcheck-duplicateExpression": [ "severity:STYLE" ], - "duplicateExpressionTernary": [ + "cppcheck-duplicateExpressionTernary": [ "severity:STYLE" ], - "duplicateValueTernary": [ + "cppcheck-duplicateValueTernary": [ "severity:STYLE" ], - "eraseDereference": [ + "cppcheck-eraseDereference": [ + "profile:default", "severity:HIGH" ], - "exceptDeallocThrow": [ + "cppcheck-exceptDeallocThrow": [ + "profile:default", "severity:MEDIUM" ], - "exceptRethrowCopy": [ + "cppcheck-exceptRethrowCopy": [ "severity:STYLE" ], - "exceptThrowInDestructor": [ + "cppcheck-exceptThrowInDestructor": [ + "profile:default", "severity:MEDIUM" ], - "fflushOnInputStream": [ + "cppcheck-fflushOnInputStream": [ "severity:LOW" ], - "floatConversionOverflow": [ + "cppcheck-floatConversionOverflow": [ + "profile:default", "severity:HIGH" ], - "funcArgNamesDifferent": [ + "cppcheck-funcArgNamesDifferent": [ "severity:STYLE" ], - "funcArgOrderDifferent": [ + "cppcheck-funcArgOrderDifferent": [ + "profile:default", "severity:MEDIUM" ], - "functionConst": [ + "cppcheck-functionConst": [ "severity:STYLE" ], - "functionStatic": [ + "cppcheck-functionStatic": [ "severity:LOW" ], - "globalLockGuard": [ + "cppcheck-globalLockGuard": [ + "severity:MEDIUM" + ], + "cppcheck-identicalConditionAfterEarlyExit": [ + "profile:default", "severity:MEDIUM" ], - "identicalConditionAfterEarlyExit": [ + "cppcheck-identicalInnerCondition": [ + "profile:default", "severity:MEDIUM" ], - "identicalInnerCondition": [ + "cppcheck-ignoredReturnValue": [ + "profile:default", "severity:MEDIUM" ], - "ignoredReturnValue": [ + "cppcheck-incompatibleFileOpen": [ + "profile:default", "severity:MEDIUM" ], - "incompleteArrayFill": [ + "cppcheck-incompleteArrayFill": [ + "profile:default", "severity:MEDIUM" ], - "incorrectCharBooleanError": [ + "cppcheck-incorrectCharBooleanError": [ + "profile:default", "severity:MEDIUM" ], - "incorrectLogicOperator": [ + "cppcheck-incorrectLogicOperator": [ + "profile:default", "severity:MEDIUM" ], - "incorrectStringBooleanError": [ + "cppcheck-incorrectStringBooleanError": [ + "profile:default", "severity:MEDIUM" ], - "incorrectStringCompare": [ + "cppcheck-incorrectStringCompare": [ + "profile:default", "severity:MEDIUM" ], - "incrementboolean": [ + "cppcheck-incrementboolean": [ "severity:STYLE" ], - "initializerList": [ + "cppcheck-initializerList": [ "severity:STYLE" ], - "integerOverflow": [ + "cppcheck-integerOverflow": [ + "profile:default", "severity:HIGH" ], - "invalidContainer": [ + "cppcheck-invalidContainer": [ + "profile:default", "severity:HIGH" ], - "invalidContainerLoop": [ + "cppcheck-invalidContainerLoop": [ "severity:HIGH" ], - "invalidFree": [ + "cppcheck-invalidFree": [ + "profile:default", "severity:HIGH" ], - "invalidFunctionArg": [ + "cppcheck-invalidFunctionArg": [ + "profile:default", "severity:HIGH" ], - "invalidFunctionArgBool": [ + "cppcheck-invalidFunctionArgBool": [ + "profile:default", "severity:HIGH" ], - "invalidFunctionArgStr": [ + "cppcheck-invalidFunctionArgStr": [ + "profile:default", "severity:HIGH" ], - "invalidIterator1": [ + "cppcheck-invalidIterator1": [ + "profile:default", "severity:HIGH" ], - "invalidLengthModifierError": [ + "cppcheck-invalidLengthModifierError": [ + "profile:default", "severity:MEDIUM" ], - "invalidLifetime": [ + "cppcheck-invalidLifetime": [ + "profile:default", "severity:HIGH" ], - "invalidPointerCast": [ + "cppcheck-invalidPointerCast": [ "severity:LOW" ], - "invalidPrintfArgType_float": [ + "cppcheck-invalidPrintfArgType_float": [ + "profile:default", "severity:MEDIUM" ], - "invalidPrintfArgType_n": [ + "cppcheck-invalidPrintfArgType_n": [ + "profile:default", "severity:MEDIUM" ], - "invalidPrintfArgType_p": [ + "cppcheck-invalidPrintfArgType_p": [ + "profile:default", "severity:MEDIUM" ], - "invalidPrintfArgType_s": [ + "cppcheck-invalidPrintfArgType_s": [ + "profile:default", "severity:MEDIUM" ], - "invalidPrintfArgType_sint": [ + "cppcheck-invalidPrintfArgType_sint": [ + "profile:default", "severity:MEDIUM" ], - "invalidPrintfArgType_uint": [ + "cppcheck-invalidPrintfArgType_uint": [ + "profile:default", "severity:MEDIUM" ], - "invalidScanfArgType_float": [ + "cppcheck-invalidScanfArgType_float": [ + "profile:default", "severity:MEDIUM" ], - "invalidScanfArgType_int": [ + "cppcheck-invalidScanfArgType_int": [ + "profile:default", "severity:MEDIUM" ], - "invalidScanfArgType_s": [ + "cppcheck-invalidScanfArgType_s": [ + "profile:default", "severity:MEDIUM" ], - "invalidScanfFormatWidth": [ + "cppcheck-invalidScanfFormatWidth": [ + "profile:default", "severity:HIGH" ], - "invalidScanfFormatWidth_smaller": [ + "cppcheck-invalidScanfFormatWidth_smaller": [ + "profile:default", "severity:MEDIUM" ], - "invalidTestForOverflow": [ + "cppcheck-invalidTestForOverflow": [ + "profile:default", "severity:MEDIUM" ], - "invalidscanf": [ + "cppcheck-invalidscanf": [ + "profile:default", "severity:MEDIUM" ], - "iterators1": [ + "cppcheck-iterators1": [ + "profile:default", + "severity:HIGH" + ], + "cppcheck-iterators2": [ + "profile:default", "severity:HIGH" ], - "iterators2": [ + "cppcheck-iterators3": [ + "profile:default", "severity:HIGH" ], - "iterators3": [ + "cppcheck-iteratorsCmp1": [ + "profile:default", "severity:HIGH" ], - "knownArgument": [ + "cppcheck-iteratorsCmp2": [ + "profile:default", + "severity:HIGH" + ], + "cppcheck-knownArgument": [ "severity:STYLE" ], - "knownArgumentHiddenVariableExpression": [ + "cppcheck-knownArgumentHiddenVariableExpression": [ "severity:STYLE" ], - "knownConditionTrueFalse": [ + "cppcheck-knownConditionTrueFalse": [ "severity:STYLE" ], - "knownEmptyContainer": [ + "cppcheck-knownEmptyContainer": [ "severity:STYLE" ], - "leakNoVarFunctionCall": [ + "cppcheck-leakNoVarFunctionCall": [ + "profile:default", "severity:HIGH" ], - "leakReturnValNotUsed": [ + "cppcheck-leakReturnValNotUsed": [ + "profile:default", "severity:HIGH" ], - "leakUnsafeArgAlloc": [ + "cppcheck-leakUnsafeArgAlloc": [ + "profile:default", "severity:MEDIUM" ], - "literalWithCharPtrCompare": [ + "cppcheck-literalWithCharPtrCompare": [ + "profile:default", "severity:MEDIUM" ], - "localMutex": [ + "cppcheck-localMutex": [ "severity:MEDIUM" ], - "mallocOnClassError": [ + "cppcheck-mallocOnClassError": [ + "profile:default", "severity:HIGH" ], - "mallocOnClassWarning": [ + "cppcheck-mallocOnClassWarning": [ + "profile:default", "severity:MEDIUM" ], - "memleak": [ + "cppcheck-memleak": [ + "profile:default", "severity:HIGH" ], - "memleakOnRealloc": [ + "cppcheck-memleakOnRealloc": [ + "profile:default", "severity:HIGH" ], - "memsetClass": [ + "cppcheck-memsetClass": [ + "profile:default", "severity:HIGH" ], - "memsetClassFloat": [ + "cppcheck-memsetClassFloat": [ "severity:LOW" ], - "memsetClassReference": [ + "cppcheck-memsetClassReference": [ + "profile:default", "severity:HIGH" ], - "memsetFloat": [ + "cppcheck-memsetFloat": [ "severity:LOW" ], - "memsetValueOutOfRange": [ + "cppcheck-memsetValueOutOfRange": [ + "profile:default", "severity:MEDIUM" ], - "memsetZeroBytes": [ + "cppcheck-memsetZeroBytes": [ + "profile:default", "severity:MEDIUM" ], - "mismatchAllocDealloc": [ + "cppcheck-mismatchAllocDealloc": [ + "profile:default", "severity:HIGH" ], - "mismatchSize": [ + "cppcheck-mismatchSize": [ + "profile:default", "severity:HIGH" ], - "mismatchingBitAnd": [ + "cppcheck-mismatchingBitAnd": [ "severity:STYLE" ], - "mismatchingContainerExpression": [ + "cppcheck-mismatchingContainerExpression": [ + "profile:default", "severity:MEDIUM" ], - "mismatchingContainerIterator": [ + "cppcheck-mismatchingContainerIterator": [ "severity:HIGH" ], - "mismatchingContainers": [ + "cppcheck-mismatchingContainers": [ + "profile:default", "severity:HIGH" ], - "missingInclude": [ + "cppcheck-missingInclude": [ "severity:LOW" ], - "missingIncludeSystem": [ + "cppcheck-missingIncludeSystem": [ "severity:LOW" ], - "missingOverride": [ + "cppcheck-missingMemberCopy": [ + "profile:default", + "severity:MEDIUM" + ], + "cppcheck-missingOverride": [ "severity:STYLE" ], - "moduloAlwaysTrueFalse": [ + "cppcheck-missingReturn": [ + "profile:default", + "severity:HIGH" + ], + "cppcheck-moduloAlwaysTrueFalse": [ + "profile:default", "severity:MEDIUM" ], - "moduloofone": [ + "cppcheck-moduloofone": [ "severity:STYLE" ], - "multiCondition": [ + "cppcheck-multiCondition": [ "severity:STYLE" ], - "multiplySizeof": [ + "cppcheck-multiplySizeof": [ + "profile:default", "severity:MEDIUM" ], - "nanInArithmeticExpression": [ + "cppcheck-nanInArithmeticExpression": [ "severity:STYLE" ], - "negativeContainerIndex": [ + "cppcheck-negativeArraySize": [ + "profile:default", "severity:HIGH" ], - "negativeIndex": [ + "cppcheck-negativeContainerIndex": [ + "profile:default", "severity:HIGH" ], - "noConstructor": [ + "cppcheck-negativeIndex": [ + "profile:default", + "severity:HIGH" + ], + "cppcheck-negativeMemoryAllocationSize": [ + "profile:default", + "severity:HIGH" + ], + "cppcheck-noConstructor": [ "severity:STYLE" ], - "noCopyConstructor": [ + "cppcheck-noCopyConstructor": [ + "profile:default", "severity:MEDIUM" ], - "noDestructor": [ + "cppcheck-noDestructor": [ + "profile:default", "severity:MEDIUM" ], - "noExplicitConstructor": [ + "cppcheck-noExplicitConstructor": [ "severity:STYLE" ], - "noOperatorEq": [ + "cppcheck-noOperatorEq": [ + "profile:default", "severity:MEDIUM" ], - "nullPointer": [ + "cppcheck-nullPointer": [ + "profile:default", "severity:HIGH" ], - "nullPointerArithmetic": [ + "cppcheck-nullPointerArithmetic": [ + "profile:default", "severity:HIGH" ], - "nullPointerArithmeticRedundantCheck": [ + "cppcheck-nullPointerArithmeticRedundantCheck": [ + "profile:default", "severity:MEDIUM" ], - "nullPointerDefaultArg": [ + "cppcheck-nullPointerDefaultArg": [ + "profile:default", "severity:MEDIUM" ], - "nullPointerRedundantCheck": [ + "cppcheck-nullPointerRedundantCheck": [ + "profile:default", "severity:MEDIUM" ], - "objectIndex": [ + "cppcheck-objectIndex": [ + "profile:default", "severity:HIGH" ], - "operatorEqMissingReturnStatement": [ + "cppcheck-operatorEqMissingReturnStatement": [ + "profile:default", "severity:HIGH" ], - "operatorEqRetRefThis": [ + "cppcheck-operatorEqRetRefThis": [ "severity:STYLE" ], - "operatorEqShouldBeLeftUnimplemented": [ + "cppcheck-operatorEqShouldBeLeftUnimplemented": [ "severity:STYLE" ], - "operatorEqToSelf": [ + "cppcheck-operatorEqToSelf": [ + "profile:default", "severity:MEDIUM" ], - "operatorEqVarError": [ + "cppcheck-operatorEqVarError": [ + "profile:default", "severity:MEDIUM" ], - "oppositeExpression": [ + "cppcheck-oppositeExpression": [ "severity:STYLE" ], - "oppositeInnerCondition": [ + "cppcheck-oppositeInnerCondition": [ + "profile:default", "severity:MEDIUM" ], - "overlappingStrcmp": [ + "cppcheck-overlappingStrcmp": [ + "profile:default", "severity:MEDIUM" ], - "passedByValue": [ + "cppcheck-overlappingWriteFunction": [ + "profile:default", + "severity:HIGH" + ], + "cppcheck-overlappingWriteUnion": [ + "profile:default", + "severity:HIGH" + ], + "cppcheck-passedByValue": [ "severity:LOW" ], - "pointerAdditionResultNotNull": [ + "cppcheck-pointerAdditionResultNotNull": [ + "profile:default", "severity:MEDIUM" ], - "pointerArithBool": [ + "cppcheck-pointerArithBool": [ + "profile:default", "severity:HIGH" ], - "pointerLessThanZero": [ + "cppcheck-pointerLessThanZero": [ "severity:STYLE" ], - "pointerOutOfBounds": [ + "cppcheck-pointerOutOfBounds": [ "severity:LOW" ], - "pointerPositive": [ + "cppcheck-pointerPositive": [ "severity:STYLE" ], - "pointerSize": [ + "cppcheck-pointerSize": [ + "profile:default", "severity:MEDIUM" ], - "postfixOperator": [ + "cppcheck-postfixOperator": [ "severity:LOW" ], - "preprocessorErrorDirective": [ + "cppcheck-preprocessorErrorDirective": [ + "profile:default", "severity:HIGH" ], - "publicAllocationError": [ + "cppcheck-publicAllocationError": [ + "profile:default", "severity:MEDIUM" ], - "pureVirtualCall": [ + "cppcheck-pureVirtualCall": [ + "profile:default", "severity:MEDIUM" ], - "purgedConfiguration": [ + "cppcheck-purgedConfiguration": [ "severity:LOW" ], - "raceAfterInterlockedDecrement": [ + "cppcheck-raceAfterInterlockedDecrement": [ + "profile:default", "severity:HIGH" ], - "readWriteOnlyFile": [ + "cppcheck-readWriteOnlyFile": [ + "profile:default", "severity:HIGH" ], - "reademptycontainer": [ + "cppcheck-reademptycontainer": [ "severity:STYLE" ], - "redundantAssignInSwitch": [ + "cppcheck-redundantAssignInSwitch": [ + "profile:default", "severity:STYLE" ], - "redundantAssignment": [ + "cppcheck-redundantAssignment": [ "severity:STYLE" ], - "redundantBitwiseOperationInSwitch": [ + "cppcheck-redundantBitwiseOperationInSwitch": [ + "profile:default", "severity:STYLE" ], - "redundantCondition": [ + "cppcheck-redundantCondition": [ "severity:STYLE" ], - "redundantCopy": [ + "cppcheck-redundantCopy": [ "severity:LOW" ], - "redundantCopyInSwitch": [ + "cppcheck-redundantCopyInSwitch": [ + "profile:default", "severity:STYLE" ], - "redundantCopyLocalConst": [ + "cppcheck-redundantCopyLocalConst": [ "severity:LOW" ], - "redundantIfRemove": [ + "cppcheck-redundantIfRemove": [ "severity:STYLE" ], - "redundantInitialization": [ + "cppcheck-redundantInitialization": [ "severity:STYLE" ], - "redundantPointerOp": [ + "cppcheck-redundantPointerOp": [ "severity:STYLE" ], - "resourceLeak": [ + "cppcheck-resourceLeak": [ + "profile:default", + "severity:HIGH" + ], + "cppcheck-rethrowNoCurrentException": [ + "profile:default", "severity:HIGH" ], - "returnAddressOfAutoVariable": [ + "cppcheck-returnAddressOfAutoVariable": [ + "profile:default", "severity:HIGH" ], - "returnAddressOfFunctionParameter": [ + "cppcheck-returnAddressOfFunctionParameter": [ + "profile:default", "severity:HIGH" ], - "returnDanglingLifetime": [ + "cppcheck-returnDanglingLifetime": [ + "profile:default", "severity:HIGH" ], - "returnLocalVariable": [ + "cppcheck-returnLocalVariable": [ + "profile:default", "severity:HIGH" ], - "returnNonBoolInBooleanFunction": [ + "cppcheck-returnNonBoolInBooleanFunction": [ "severity:STYLE" ], - "returnReference": [ + "cppcheck-returnReference": [ + "profile:default", "severity:HIGH" ], - "returnTempReference": [ + "cppcheck-returnTempReference": [ + "profile:default", "severity:HIGH" ], - "sameIteratorExpression": [ + "cppcheck-returnStdMoveLocal": [ + "severity:LOW" + ], + "cppcheck-sameIteratorExpression": [ "severity:STYLE" ], - "seekOnAppendedFile": [ + "cppcheck-seekOnAppendedFile": [ + "profile:default", "severity:MEDIUM" ], - "selfAssignment": [ + "cppcheck-selfAssignment": [ + "profile:default", "severity:MEDIUM" ], - "selfInitialization": [ + "cppcheck-selfInitialization": [ + "profile:default", "severity:HIGH" ], - "shadowArgument": [ + "cppcheck-shadowArgument": [ "severity:STYLE" ], - "shadowFunction": [ + "cppcheck-shadowFunction": [ "severity:STYLE" ], - "shadowVariable": [ + "cppcheck-shadowVariable": [ "severity:STYLE" ], - "shiftNegative": [ + "cppcheck-shiftNegative": [ + "profile:default", "severity:HIGH" ], - "shiftNegativeLHS": [ + "cppcheck-shiftNegativeLHS": [ "severity:LOW" ], - "shiftTooManyBits": [ + "cppcheck-shiftTooManyBits": [ + "profile:default", "severity:HIGH" ], - "shiftTooManyBitsSigned": [ + "cppcheck-shiftTooManyBitsSigned": [ + "profile:default", "severity:HIGH" ], - "signConversion": [ + "cppcheck-signConversion": [ + "profile:default", "severity:MEDIUM" ], - "signedCharArrayIndex": [ + "cppcheck-signedCharArrayIndex": [ + "profile:default", "severity:MEDIUM" ], - "sizeofCalculation": [ + "cppcheck-sizeofCalculation": [ + "profile:default", "severity:MEDIUM" ], - "sizeofDereferencedVoidPointer": [ + "cppcheck-sizeofDereferencedVoidPointer": [ "severity:LOW" ], - "sizeofDivisionMemfunc": [ + "cppcheck-sizeofDivisionMemfunc": [ + "profile:default", "severity:MEDIUM" ], - "sizeofFunctionCall": [ + "cppcheck-sizeofFunctionCall": [ + "profile:default", "severity:MEDIUM" ], - "sizeofVoid": [ + "cppcheck-sizeofVoid": [ "severity:LOW" ], - "sizeofsizeof": [ + "cppcheck-sizeofsizeof": [ + "profile:default", "severity:MEDIUM" ], - "sizeofwithnumericparameter": [ + "cppcheck-sizeofwithnumericparameter": [ + "profile:default", "severity:MEDIUM" ], - "sizeofwithsilentarraypointer": [ + "cppcheck-sizeofwithsilentarraypointer": [ + "profile:default", "severity:MEDIUM" ], - "sprintfOverlappingData": [ + "cppcheck-sprintfOverlappingData": [ + "profile:default", "severity:HIGH" ], - "staticStringCompare": [ + "cppcheck-staticStringCompare": [ + "profile:default", "severity:MEDIUM" ], - "stlBoundaries": [ + "cppcheck-stlBoundaries": [ + "profile:default", "severity:HIGH" ], - "stlFindInsert": [ + "cppcheck-stlFindInsert": [ "severity:LOW" ], - "stlIfFind": [ + "cppcheck-stlIfFind": [ + "profile:default", "severity:MEDIUM" ], - "stlIfStrFind": [ + "cppcheck-stlIfStrFind": [ "severity:LOW" ], - "stlOutOfBounds": [ + "cppcheck-stlOutOfBounds": [ + "profile:default", "severity:HIGH" ], - "stlSize": [ + "cppcheck-stlSize": [ "severity:LOW" ], - "stlcstr": [ + "cppcheck-stlcstr": [ + "profile:default", "severity:HIGH" ], - "stlcstrParam": [ + "cppcheck-stlcstrParam": [ "severity:LOW" ], - "stlcstrReturn": [ + "cppcheck-stlcstrReturn": [ "severity:LOW" ], - "stlcstrthrow": [ + "cppcheck-stlcstrthrow": [ + "profile:default", "severity:HIGH" ], - "strPlusChar": [ + "cppcheck-strPlusChar": [ + "profile:default", "severity:HIGH" ], - "stringCompare": [ + "cppcheck-stringCompare": [ + "profile:default", "severity:MEDIUM" ], - "stringLiteralWrite": [ + "cppcheck-stringLiteralWrite": [ + "profile:default", "severity:HIGH" ], - "suspiciousCase": [ + "cppcheck-suspiciousCase": [ + "profile:default", "severity:MEDIUM" ], - "suspiciousSemicolon": [ + "cppcheck-suspiciousSemicolon": [ + "profile:default", "severity:MEDIUM" ], - "thisSubtraction": [ + "cppcheck-thisSubtraction": [ + "profile:default", "severity:MEDIUM" ], - "thisUseAfterFree": [ + "cppcheck-thisUseAfterFree": [ "severity:MEDIUM" ], - "throwInNoexceptFunction": [ + "cppcheck-throwInNoexceptFunction": [ + "profile:default", "severity:HIGH" ], - "toomanyconfigs": [ + "cppcheck-toomanyconfigs": [ "severity:LOW" ], - "truncLongCastAssignment": [ + "cppcheck-truncLongCastAssignment": [ "severity:STYLE" ], - "truncLongCastReturn": [ + "cppcheck-truncLongCastReturn": [ "severity:STYLE" ], - "unassignedVariable": [ + "cppcheck-unassignedVariable": [ "severity:STYLE" ], - "unhandledExceptionSpecification": [ + "cppcheck-unhandledExceptionSpecification": [ "severity:STYLE" ], - "uninitMemberVar": [ + "cppcheck-uninitDerivedMemberVar": [ + "profile:default", + "severity:MEDIUM" + ], + "cppcheck-uninitDerivedMemberVarPrivate": [ + "profile:default", + "severity:MEDIUM" + ], + "cppcheck-uninitMemberVar": [ + "profile:default", "severity:MEDIUM" ], - "uninitMemberVarPrivate": [ + "cppcheck-uninitMemberVarPrivate": [ + "profile:default", "severity:MEDIUM" ], - "uninitStructMember": [ + "cppcheck-uninitStructMember": [ + "profile:default", "severity:HIGH" ], - "uninitdata": [ + "cppcheck-uninitdata": [ + "profile:default", "severity:HIGH" ], - "uninitstring": [ + "cppcheck-uninitstring": [ + "profile:default", "severity:HIGH" ], - "uninitvar": [ + "cppcheck-uninitvar": [ + "profile:default", "severity:HIGH" ], - "unknownEvaluationOrder": [ + "cppcheck-unknownEvaluationOrder": [ + "profile:default", "severity:HIGH" ], - "unknownSignCharArrayIndex": [ + "cppcheck-unknownSignCharArrayIndex": [ "severity:LOW" ], - "unpreciseMathCall": [ + "cppcheck-unpreciseMathCall": [ "severity:STYLE" ], - "unreachableCode": [ + "cppcheck-unreachableCode": [ "severity:STYLE" ], - "unreadVariable": [ + "cppcheck-unreadVariable": [ "severity:STYLE" ], - "unsafeClassCanLeak": [ + "cppcheck-unsafeClassCanLeak": [ "severity:STYLE" ], - "unsafeClassRefMember": [ + "cppcheck-unsafeClassRefMember": [ + "profile:default", "severity:MEDIUM" ], - "unsignedLessThanZero": [ + "cppcheck-unsignedLessThanZero": [ "severity:STYLE" ], - "unsignedPositive": [ + "cppcheck-unsignedPositive": [ "severity:STYLE" ], - "unusedAllocatedMemory": [ + "cppcheck-unusedAllocatedMemory": [ "severity:STYLE" ], - "unusedFunction": [ + "cppcheck-unusedFunction": [ "severity:STYLE" ], - "unusedLabel": [ + "cppcheck-unusedLabel": [ "severity:STYLE" ], - "unusedLabelConfiguration": [ + "cppcheck-unusedLabelConfiguration": [ "severity:STYLE" ], - "unusedLabelSwitch": [ + "cppcheck-unusedLabelSwitch": [ + "profile:default", "severity:MEDIUM" ], - "unusedLabelSwitchConfiguration": [ + "cppcheck-unusedLabelSwitchConfiguration": [ "severity:MEDIUM" ], - "unusedPrivateFunction": [ + "cppcheck-unusedPrivateFunction": [ "severity:STYLE" ], - "unusedScopedObject": [ + "cppcheck-unusedScopedObject": [ "severity:STYLE" ], - "unusedStructMember": [ + "cppcheck-unusedStructMember": [ "severity:STYLE" ], - "unusedVariable": [ + "cppcheck-unusedVariable": [ "severity:STYLE" ], - "useClosedFile": [ + "cppcheck-useClosedFile": [ + "profile:default", "severity:HIGH" ], - "useInitializationList": [ + "cppcheck-useInitializationList": [ "severity:LOW" ], - "useStlAlgorithm": [ + "cppcheck-useStlAlgorithm": [ "severity:STYLE" ], - "uselessAssignmentArg": [ + "cppcheck-uselessAssignmentArg": [ "severity:STYLE" ], - "uselessAssignmentPtrArg": [ + "cppcheck-uselessAssignmentPtrArg": [ + "profile:default", "severity:MEDIUM" ], - "uselessCallsCompare": [ + "cppcheck-uselessCallsCompare": [ + "profile:default", "severity:MEDIUM" ], - "uselessCallsEmpty": [ + "cppcheck-uselessCallsEmpty": [ + "profile:default", "severity:MEDIUM" ], - "uselessCallsRemove": [ + "cppcheck-uselessCallsRemove": [ + "profile:default", "severity:MEDIUM" ], - "uselessCallsSubstr": [ + "cppcheck-uselessCallsSubstr": [ "severity:LOW" ], - "uselessCallsSwap": [ + "cppcheck-uselessCallsSwap": [ "severity:LOW" ], - "va_end_missing": [ + "cppcheck-va_end_missing": [ + "profile:default", "severity:HIGH" ], - "va_list_usedBeforeStarted": [ + "cppcheck-va_list_usedBeforeStarted": [ + "profile:default", "severity:HIGH" ], - "va_start_referencePassed": [ + "cppcheck-va_start_referencePassed": [ + "profile:default", "severity:HIGH" ], - "va_start_subsequentCalls": [ + "cppcheck-va_start_subsequentCalls": [ + "profile:default", "severity:HIGH" ], - "va_start_wrongParameter": [ + "cppcheck-va_start_wrongParameter": [ + "profile:default", "severity:MEDIUM" ], - "varFuncNullUB": [ + "cppcheck-varFuncNullUB": [ "severity:LOW" ], - "variableScope": [ + "cppcheck-variableScope": [ "severity:STYLE" ], - "virtualCallInConstructor": [ + "cppcheck-virtualCallInConstructor": [ + "profile:default", "severity:STYLE" ], - "virtualDestructor": [ + "cppcheck-virtualDestructor": [ + "profile:default", "severity:HIGH" ], - "writeReadOnlyFile": [ + "cppcheck-writeReadOnlyFile": [ + "profile:default", "severity:HIGH" ], - "wrongPipeParameterSize": [ + "cppcheck-wrongPipeParameterSize": [ + "profile:default", "severity:HIGH" ], - "wrongPrintfScanfArgNum": [ + "cppcheck-wrongPrintfScanfArgNum": [ + "profile:default", "severity:HIGH" ], - "wrongPrintfScanfParameterPositionError": [ + "cppcheck-wrongPrintfScanfParameterPositionError": [ + "profile:default", "severity:MEDIUM" ], - "wrongmathcall": [ + "cppcheck-wrongmathcall": [ + "profile:default", "severity:MEDIUM" ], - "zerodiv": [ + "cppcheck-zerodiv": [ + "profile:default", "severity:HIGH" ], - "zerodivcond": [ + "cppcheck-zerodivcond": [ + "profile:default", "severity:HIGH" ] } diff --git a/config/package_layout.json b/config/package_layout.json index dd13be8531..abfef0572f 100644 --- a/config/package_layout.json +++ b/config/package_layout.json @@ -2,7 +2,8 @@ "runtime": { "analyzers": { "clangsa": "clang", - "clang-tidy": "clang-tidy" + "clang-tidy": "clang-tidy", + "cppcheck": "cppcheck" }, "clang-apply-replacements": "clang-apply-replacements" }, diff --git a/docs/README.md b/docs/README.md index c0d849bdc4..839a3e8f9c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -36,7 +36,7 @@ macOS (OS X) development environment. # Main features ## Command line C/C++ Analysis - * Executes [_Clang-Tidy_](http://clang.llvm.org/extra/clang-tidy/) and [_Clang Static Analyzer_](http://clang-analyzer.llvm.org/) with Cross-Translation Unit analysis, Statistical Analysis (when checkers are available). + * Executes [_Clang-Tidy_](http://clang.llvm.org/extra/clang-tidy/), [_Clang Static Analyzer_](http://clang-analyzer.llvm.org/) with Cross-Translation Unit analysis, Statistical Analysis (when checkers are available), and [_Cppcheck_](https://cppcheck.sourceforge.io/). * Creates the JSON compilation database by wiretapping any build process (e.g., `CodeChecker log -b "make"`). * Automatically analyzes GCC cross-compiled projects: detecting GCC or Clang compiler configuration and forming the corresponding clang analyzer invocations. * Incremental analysis: Only the changed files and its dependencies need to be reanalyzed. @@ -239,7 +239,8 @@ The following commands are used to bootstrap CodeChecker on Ubuntu 20.04 LTS: # Install mandatory dependencies for a development and analysis environment. # NOTE: clang or clang-tidy can be any sufficiently fresh version, and need not # come from package manager! -sudo apt-get install clang clang-tidy build-essential curl gcc-multilib \ +# In case of Cppcheck, the minimal supported version is 1.80. +sudo apt-get install clang clang-tidy cppcheck build-essential curl gcc-multilib \ git python3-dev python3-venv # Install nodejs dependency for web. In case of Debian/Ubuntu you can use the diff --git a/docs/analyzer/checker_and_analyzer_configuration.md b/docs/analyzer/checker_and_analyzer_configuration.md index 984c3a52dc..3620677d2f 100644 --- a/docs/analyzer/checker_and_analyzer_configuration.md +++ b/docs/analyzer/checker_and_analyzer_configuration.md @@ -191,3 +191,73 @@ configuration arguments (json in this case) should be in one line : ``` -config="{ "Checks": "clang-diagnostic-*,clang-analyzer-*", "WarningsAsErrors": "", "HeaderFilterRegex": "", "AnalyzeTemporaryDtors": false, "CheckOptions": [ { "key": "google-readability-braces-around-statements.ShortStatementLines", "value": "1" }, { "key": "modernize-loop-convert.MaxCopySize", "value": "16" }, { "key": "modernize-loop-convert.NamingStyle", "value": "CamelCase" }, { "key": "modernize-use-nullptr.NullMacros", "value": "NULL" } ] }" ``` + +# Cppcheck + +As of CodeChecker 6.20, Codechecker can now execute the Cppcheck analyzer. + +## Configuration + +The Cppcheck analyzer can be configured with --analyzer-config cppcheck:* paramterers. + +The supported analyzer configuration items can be listed with `CodeChecker analyzers --analyzer-config cppcheck --details` + +As of CodeChecker 6.20, the following options are supported: + +* `cppcheck:addons` A list of Cppcheck addon files. +* `cppcheck:libraries` A list of Cppcheck library definiton files. +* `cppcheck:platform` The platform configuration .xml file. + +Please note that for addons and libraries, multiple items can be specified in the following format: `--analyzer-config cppcheck:addons --analyzer-config cppcheck:addons `. + +Cppcheck only supports a limited number of platforms. Custom bit lengths can be specified with a platform file. + +An example platform file from the Cppcheck manual: + +``` xml + + + 8 + signed + + 2 + 4 + 4 + 8 + 4 + 8 + 12 + 4 + 4 + 2 + + +``` + +## Limitations + +The following limitations need to be considered when using Cppcheck: + +* The whole program analysis feature of Cppcheck is not supported. Cppcheck is invoked for every item in the provided compilation database. + * The `cppcheck-unususedFunction` checker of Cppcheck is always disabled by default. + * The CTU functionality of Cppcheck is not supported. +* The severity categorizations are only provided for the built in checkers. Addon checkers can be used, but their reports severity will be displayed as `Unspecified`. +* The Cppcheck categorization of checkers is not yet introduced into the Cppcheck label [file](../../config/labels/analyzers/cppcheck.json). To enable a whole category, each individual checker needs to be enabled with the `--enable` flag. +* All Cppcheck Errors and Warnings are enabled by default. +* If not configured, `Native` platform will be assumed for the analyzed compilation database (i.e. the type sizes of the host system are used). No platform translation will occur by CodeChecker. If another one is needed, please provide a platform file with the correct bit lengths. +* To reach maximum compatibility with the existing CodeChecker invocation, Cppcheck is invoked with the `--enable=all` parameter, and all non-needed checkers are passed in as `--suppress=`. +* Due to legal reasons, no MISRA rule texts are supplied. + + +## Example invocation +``` shell +CodeChecker check -l ./compile_commands.json \ + --analyzers cppcheck \ # Run Cppcheck analyzer only + -e Cppcheck-missingOverride \ # enable the missingOverride Cppcheck check + -d Cppcheck-virtualCallInConstructor \ # disable the virtualCallInConstructor check + --analyzer-config cppcheck:addons=../cppcheck/addons/misc.py \ # enable the misc checks + --analyzer-config cppcheck:addons=../cppcheck/addons/cert.py \ # enable cert cheks + --analyzer-config cppcheck:libraries=../cppcheck/cfg/zlib.cfg \ # add zlib definitons + --analyzer-config cppcheck:libraries=../cppcheck/cfg/gnu.cfg \ # add gnu definitions + -o ./reports +``` diff --git a/docs/analyzer/user_guide.md b/docs/analyzer/user_guide.md index 4d17913718..e8ea7ff74d 100644 --- a/docs/analyzer/user_guide.md +++ b/docs/analyzer/user_guide.md @@ -892,9 +892,9 @@ usage: CodeChecker analyze [-h] [-j JOBS] [--compile-uniqueing COMPILE_UNIQUEING] [--report-hash {context-free,context-free-v2,diagnostic-message}] [-n NAME] [--analyzers ANALYZER [ANALYZER ...]] - [--add-compiler-defaults] [--capture-analysis-output] [--generate-reproducer] [--config CONFIG_FILE] + [--cppcheck-args CPPCHECK_ARGS_CFG_FILE] [--saargs CLANGSA_ARGS_CFG_FILE] [--tidyargs TIDY_ARGS_CFG_FILE] [--tidy-config TIDY_CONFIG] [--timeout TIMEOUT] @@ -1076,12 +1076,6 @@ analyzer arguments: Run analysis only with the analyzers specified. Currently supported analyzers are: clangsa, clang- tidy. - --add-compiler-defaults - DEPRECATED. Always True. - Retrieve compiler-specific configuration from the - compilers themselves, and use them with Clang. This is - used when the compiler on the system is special, e.g. - when doing cross-compilation. --capture-analysis-output Store standard output and standard error of successful analyzer invocations into the '/success' @@ -1100,6 +1094,9 @@ analyzer arguments: For more information see the docs: https://github.com/ Ericsson/codechecker/tree/master/docs/config_file.md (default: None) + --cppcheck-args CPPCHECK_ARGS_CFG_FILE + Configuration file to pass cppcheck command line + arguments. --saargs CLANGSA_ARGS_CFG_FILE File containing argument which will be forwarded verbatim for the Clang Static Analyzer. @@ -1147,8 +1144,9 @@ analyzer arguments: ``` CodeChecker supports several analyzer tools. Currently, these analyzers are -the [_Clang Static Analyzer_](http://clang-analyzer.llvm.org) and -[_Clang-Tidy_](http://clang.llvm.org/extra/clang-tidy). `--analyzers` can be +the [_Clang Static Analyzer_](http://clang-analyzer.llvm.org), +[_Clang-Tidy_](http://clang.llvm.org/extra/clang-tidy) and +[_Cppcheck_](http://cppcheck.sourceforge.net/). `--analyzers` can be used to specify which analyzer tool should be used (by default, all supported are used). The tools are completely independent, so either can be omitted if not present as they are provided by different binaries. @@ -1312,12 +1310,6 @@ Example: ##### Compiler-specific include path and define detection (cross compilation) -Some of the include paths are hardcoded during compiler build. If a (cross) -compiler is used to build a project it is possible that the wrong include -paths are searched and the wrong headers will be included which causes -analyses to fail. These hardcoded include paths and defines can be marked for -automatically detection by specifying the `--add-compiler-defaults` flag. - CodeChecker will get the hardcoded values for the compilers set in the `CC_LOGGER_GCC_LIKE` environment variable. @@ -1325,14 +1317,6 @@ CodeChecker will get the hardcoded values for the compilers set in the export CC_LOGGER_GCC_LIKE="gcc:g++:clang:clang++:cc:c++" ``` -If there are still compilation errors after using the `--add-compiler-defaults` -argument, it is possible that the wrong build target architecture -(32bit, 64bit) is used. Please try to forward these compilation flags -to the analyzers: - - - `-m32` (32-bit build) - - `-m64` (64-bit build) - GCC specific hard-coded values are detected during the analysis and recorded int the `/compiler_info.json`. diff --git a/docs/supported_code_analyzers.md b/docs/supported_code_analyzers.md index 6cb61ab340..7cc03d298a 100644 --- a/docs/supported_code_analyzers.md +++ b/docs/supported_code_analyzers.md @@ -1,8 +1,9 @@ ## Code Analysis tools -CodeChecker can execute two main `C/C++` static analyzer tools: +CodeChecker can execute three main `C/C++` static analyzer tools: - [Clang Tidy](https://clang.llvm.org/extra/clang-tidy/) - [Clang Static Analyzer](https://clang-analyzer.llvm.org/) +- [Cppcheck](https://cppcheck.sourceforge.io/) We have created a separate [converter tool](/tools/report-converter) which can be used to convert the output of different source code analyzer tools to a diff --git a/tools/report-converter/codechecker_report_converter/analyzers/cppcheck/analyzer_result.py b/tools/report-converter/codechecker_report_converter/analyzers/cppcheck/analyzer_result.py index 59b7e0da56..fbfae3cf05 100644 --- a/tools/report-converter/codechecker_report_converter/analyzers/cppcheck/analyzer_result.py +++ b/tools/report-converter/codechecker_report_converter/analyzers/cppcheck/analyzer_result.py @@ -13,7 +13,8 @@ from typing import Dict, List -from codechecker_report_converter.report import File, Report, report_file +from codechecker_report_converter.report import BugPathEvent, \ + Range, File, Report, report_file from ..analyzer_result import AnalyzerResultBase @@ -50,4 +51,20 @@ def get_reports(self, analyzer_result_path: str) -> List[Report]: plist_file, None, file_cache) reports.extend(plist_reports) + # Until we refactor the gui to indicate the error in the location of + # the diagnostic message, we should add diagnostic message as the + # last bug path event. + for report in reports: + bpe = BugPathEvent( + report.message, + report.file, + report.line, + report.column, + Range(report.line, + report.column, + report.line, + report.column)) + if bpe != report.bug_path_events[-1]: + report.bug_path_events.append(bpe) + return reports diff --git a/tools/report-converter/tests/unit/analyzers/cppcheck_output_test_files/divide_zero.expected.plist b/tools/report-converter/tests/unit/analyzers/cppcheck_output_test_files/divide_zero.expected.plist index 073a30224c..0ebfb18a09 100644 --- a/tools/report-converter/tests/unit/analyzers/cppcheck_output_test_files/divide_zero.expected.plist +++ b/tools/report-converter/tests/unit/analyzers/cppcheck_output_test_files/divide_zero.expected.plist @@ -62,6 +62,44 @@ + + depth + 0 + kind + event + location + + col + 13 + file + 0 + line + 17 + + message + Division by zero. + ranges + + + + col + 13 + file + 0 + line + 17 + + + col + 13 + file + 0 + line + 17 + + + + type cppcheck diff --git a/web/tests/functional/comment/__init__.py b/web/tests/functional/comment/__init__.py index f6bb4d8bac..3a466e0df7 100644 --- a/web/tests/functional/comment/__init__.py +++ b/web/tests/functional/comment/__init__.py @@ -53,7 +53,8 @@ def setup_package(): 'workspace': TEST_WORKSPACE, 'reportdir': os.path.join(TEST_WORKSPACE, 'reports'), 'checkers': ['-d', 'core.CallAndMessage', - '-e', 'core.StackAddressEscape'] + '-e', 'core.StackAddressEscape'], + 'analyzers': ['clangsa', 'clang-tidy'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/component/__init__.py b/web/tests/functional/component/__init__.py index 6013277e1e..17c305087b 100644 --- a/web/tests/functional/component/__init__.py +++ b/web/tests/functional/component/__init__.py @@ -56,7 +56,8 @@ def setup_package(): 'skip_list_file': skip_list_file, 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/db_cleanup/__init__.py b/web/tests/functional/db_cleanup/__init__.py index 14b9152d89..f6cc3f9a48 100644 --- a/web/tests/functional/db_cleanup/__init__.py +++ b/web/tests/functional/db_cleanup/__init__.py @@ -37,7 +37,8 @@ def setup_package(): 'checkers': [], 'viewer_host': 'localhost', 'viewer_product': 'db_cleanup', - 'reportdir': os.path.join(TEST_WORKSPACE, 'reports') + 'reportdir': os.path.join(TEST_WORKSPACE, 'reports'), + 'analyzers': ['clangsa', 'clang-tidy'] } env.export_test_cfg(TEST_WORKSPACE, {'codechecker_cfg': codechecker_cfg}) diff --git a/web/tests/functional/delete_runs/__init__.py b/web/tests/functional/delete_runs/__init__.py index f9b09932d2..fea3e6373a 100644 --- a/web/tests/functional/delete_runs/__init__.py +++ b/web/tests/functional/delete_runs/__init__.py @@ -67,7 +67,8 @@ def setup_package(): 'skip_list_file': skip_list_file, 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/detection_status/__init__.py b/web/tests/functional/detection_status/__init__.py index 9e50f4dec4..6faff00d64 100644 --- a/web/tests/functional/detection_status/__init__.py +++ b/web/tests/functional/detection_status/__init__.py @@ -38,7 +38,8 @@ def setup_package(): 'workspace': TEST_WORKSPACE, 'checkers': [], 'reportdir': os.path.join(TEST_WORKSPACE, 'reports'), - 'test_project': 'hello' + 'test_project': 'hello', + 'analyzers': ['clangsa', 'clang-tidy'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/detection_status/test_detection_status.py b/web/tests/functional/detection_status/test_detection_status.py index bacf81bfd0..dbb08859a1 100644 --- a/web/tests/functional/detection_status/test_detection_status.py +++ b/web/tests/functional/detection_status/test_detection_status.py @@ -320,7 +320,7 @@ def test_check_without_metadata(self): None, False) - self.assertEqual(len(reports), 2) + self.assertEqual(len(reports), 5) def test_detection_status_off(self): """ diff --git a/web/tests/functional/diff_local/__init__.py b/web/tests/functional/diff_local/__init__.py index 6f25860026..c2465b6904 100644 --- a/web/tests/functional/diff_local/__init__.py +++ b/web/tests/functional/diff_local/__init__.py @@ -70,7 +70,8 @@ def setup_package(): 'skip_list_file': skip_list_file, 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } # Base analysis diff --git a/web/tests/functional/diff_local_remote/__init__.py b/web/tests/functional/diff_local_remote/__init__.py index 586412ba0b..0b7813ee63 100644 --- a/web/tests/functional/diff_local_remote/__init__.py +++ b/web/tests/functional/diff_local_remote/__init__.py @@ -71,7 +71,8 @@ def setup_package(): 'skip_list_file': skip_list_file, 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/diff_remote/__init__.py b/web/tests/functional/diff_remote/__init__.py index f3b2328290..7aa676faf6 100644 --- a/web/tests/functional/diff_remote/__init__.py +++ b/web/tests/functional/diff_remote/__init__.py @@ -76,7 +76,8 @@ def setup_package(): 'check_env': test_env, 'workspace': TEST_WORKSPACE, 'checkers': [], - 'trim_path_prefix': TEST_WORKSPACE + 'trim_path_prefix': TEST_WORKSPACE, + 'analyzers': ['clangsa'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/extended_report_data/__init__.py b/web/tests/functional/extended_report_data/__init__.py index 455aeaba0b..dcf10b2f09 100644 --- a/web/tests/functional/extended_report_data/__init__.py +++ b/web/tests/functional/extended_report_data/__init__.py @@ -37,7 +37,8 @@ def setup_package(): codechecker_cfg = { 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'run_names': [] + 'run_names': [], + 'analyzers': ['clangsa', 'clang-tidy'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/func_template/template__init__.py b/web/tests/functional/func_template/template__init__.py index a5a57d283c..2fefaecae0 100644 --- a/web/tests/functional/func_template/template__init__.py +++ b/web/tests/functional/func_template/template__init__.py @@ -79,7 +79,8 @@ def setup_package(): 'skip_list_file': skip_list_file, 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/instance_manager/__init__.py b/web/tests/functional/instance_manager/__init__.py index 40c5abef46..1e0c3dbba1 100644 --- a/web/tests/functional/instance_manager/__init__.py +++ b/web/tests/functional/instance_manager/__init__.py @@ -47,7 +47,8 @@ def setup_package(): 'workspace': TEST_WORKSPACE, 'check_env': test_env, 'run_names': [], - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } codechecker_cfg.update(host_port_cfg) test_config['codechecker_1'] = codechecker_cfg @@ -57,7 +58,8 @@ def setup_package(): 'workspace': TEST_WORKSPACE, 'check_env': test_env, 'run_names': [], - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } host_port_cfg = {'viewer_host': 'localhost', 'viewer_port': env.get_free_port()} diff --git a/web/tests/functional/products/__init__.py b/web/tests/functional/products/__init__.py index faed51c159..5b96c016fe 100644 --- a/web/tests/functional/products/__init__.py +++ b/web/tests/functional/products/__init__.py @@ -62,7 +62,8 @@ def setup_package(): codechecker_cfg = { 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/report_viewer_api/__init__.py b/web/tests/functional/report_viewer_api/__init__.py index 2abd642333..8e322bda7d 100644 --- a/web/tests/functional/report_viewer_api/__init__.py +++ b/web/tests/functional/report_viewer_api/__init__.py @@ -58,7 +58,8 @@ def setup_package(): 'check_env': test_env, 'workspace': TEST_WORKSPACE, 'checkers': ['-e', 'clang-diagnostic-return-type'], - 'tag': tag + 'tag': tag, + 'analyzers': ['clangsa', 'clang-tidy'] } ret = project.clean(test_project) diff --git a/web/tests/functional/review_status/__init__.py b/web/tests/functional/review_status/__init__.py index 3d38776ca2..1142828a69 100644 --- a/web/tests/functional/review_status/__init__.py +++ b/web/tests/functional/review_status/__init__.py @@ -52,7 +52,8 @@ def setup_package(): 'skip_list_file': skip_list_file, 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } ret = project.clean(test_project, test_env) diff --git a/web/tests/functional/run_tag/__init__.py b/web/tests/functional/run_tag/__init__.py index c00b5bf3d6..0b699de1e8 100644 --- a/web/tests/functional/run_tag/__init__.py +++ b/web/tests/functional/run_tag/__init__.py @@ -37,7 +37,8 @@ def setup_package(): 'workspace': TEST_WORKSPACE, 'checkers': [], 'reportdir': os.path.join(TEST_WORKSPACE, 'reports'), - 'test_project': 'test_run_tag' + 'test_project': 'test_run_tag', + 'analyzers': ['clangsa', 'clang-tidy'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/server_configuration/__init__.py b/web/tests/functional/server_configuration/__init__.py index 6d22595260..f336538813 100644 --- a/web/tests/functional/server_configuration/__init__.py +++ b/web/tests/functional/server_configuration/__init__.py @@ -42,7 +42,8 @@ def setup_package(): codechecker_cfg = { 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/skip/__init__.py b/web/tests/functional/skip/__init__.py index 4a00f237ca..ad4d770b5f 100644 --- a/web/tests/functional/skip/__init__.py +++ b/web/tests/functional/skip/__init__.py @@ -54,7 +54,8 @@ def setup_package(): 'skip_file': skip_list_file, 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa'] } ret = project.clean(test_project, test_env) diff --git a/web/tests/functional/source_change/__init__.py b/web/tests/functional/source_change/__init__.py index cb7d4e7d07..019edd0653 100644 --- a/web/tests/functional/source_change/__init__.py +++ b/web/tests/functional/source_change/__init__.py @@ -61,7 +61,8 @@ def setup_package(): 'check_env': test_env, 'workspace': TEST_WORKSPACE, 'reportdir': os.path.join(TEST_WORKSPACE, 'reports'), - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/functional/ssl/__init__.py b/web/tests/functional/ssl/__init__.py index 6980d4fb69..88316d123a 100644 --- a/web/tests/functional/ssl/__init__.py +++ b/web/tests/functional/ssl/__init__.py @@ -47,7 +47,8 @@ def setup_package(): codechecker_cfg = { 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } codechecker_cfg.update(host_port_cfg) diff --git a/web/tests/functional/statistics/__init__.py b/web/tests/functional/statistics/__init__.py index 772d7fe98c..debec101c6 100644 --- a/web/tests/functional/statistics/__init__.py +++ b/web/tests/functional/statistics/__init__.py @@ -65,7 +65,8 @@ def setup_package(): 'skip_list_file': skip_list_file, 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } # Clean the test project, if needed by the tests. diff --git a/web/tests/functional/storage_of_analysis_statistics/__init__.py b/web/tests/functional/storage_of_analysis_statistics/__init__.py index 00f6c222d2..fa99d4257f 100644 --- a/web/tests/functional/storage_of_analysis_statistics/__init__.py +++ b/web/tests/functional/storage_of_analysis_statistics/__init__.py @@ -47,7 +47,8 @@ def setup_package(): 'workspace': TEST_WORKSPACE, 'checkers': [], 'viewer_product': 'storage_of_analysis_statistics', - 'reportdir': os.path.join(TEST_WORKSPACE, 'reports') + 'reportdir': os.path.join(TEST_WORKSPACE, 'reports'), + 'analyzers': ['clangsa', 'clang-tidy'] } codechecker_cfg.update(host_port_cfg) diff --git a/web/tests/functional/suppress/__init__.py b/web/tests/functional/suppress/__init__.py index 2f0db9e88f..ed44f2a052 100644 --- a/web/tests/functional/suppress/__init__.py +++ b/web/tests/functional/suppress/__init__.py @@ -56,7 +56,8 @@ def setup_package(): 'skip_list_file': None, 'check_env': test_env, 'workspace': TEST_WORKSPACE, - 'checkers': [] + 'checkers': [], + 'analyzers': ['clangsa', 'clang-tidy'] } ret = project.clean(test_project, test_env) diff --git a/web/tests/functional/update/__init__.py b/web/tests/functional/update/__init__.py index 1d62679a29..0fe60a23a0 100644 --- a/web/tests/functional/update/__init__.py +++ b/web/tests/functional/update/__init__.py @@ -56,7 +56,8 @@ def setup_package(): 'check_env': test_env, 'workspace': TEST_WORKSPACE, 'checkers': [], - 'reportdir': base_reports + 'reportdir': base_reports, + 'analyzers': ['clangsa', 'clang-tidy'] } # Start or connect to the running CodeChecker server and get connection diff --git a/web/tests/libtest/codechecker.py b/web/tests/libtest/codechecker.py index 375cd17d80..953d3636ea 100644 --- a/web/tests/libtest/codechecker.py +++ b/web/tests/libtest/codechecker.py @@ -264,6 +264,11 @@ def check_and_store(codechecker_cfg, test_project_name, test_project_path, check_cmd.append('--analyzer-config') check_cmd.extend(analyzer_config) + analyzers = codechecker_cfg.get('analyzers') + if analyzers: + check_cmd.append('--analyzers') + check_cmd.extend(analyzers) + check_cmd.extend(codechecker_cfg['checkers']) try: