Skip to content

Commit

Permalink
[analyzer] Cppcheck support (#3680)
Browse files Browse the repository at this point in the history
[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 <cppcheck_check>` now properly translates to
`--suppress <cppcheck_check>` 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 <[email protected]>
Co-authored-by: bruntib <[email protected]>
Co-authored-by: vodorok <[email protected]>
  • Loading branch information
3 people authored Aug 19, 2022
1 parent 490167e commit a8cb930
Show file tree
Hide file tree
Showing 57 changed files with 1,532 additions and 365 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/install-deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
7 changes: 7 additions & 0 deletions analyzer/codechecker_analyzer/analysis_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down
15 changes: 15 additions & 0 deletions analyzer/codechecker_analyzer/analyzers/analyzer_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down Expand Up @@ -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):
"""
Expand Down
14 changes: 12 additions & 2 deletions analyzer/codechecker_analyzer/analyzers/analyzer_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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,
Expand Down
7 changes: 7 additions & 0 deletions analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down
7 changes: 7 additions & 0 deletions analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down
7 changes: 7 additions & 0 deletions analyzer/codechecker_analyzer/analyzers/cppcheck/__init__.py
Original file line number Diff line number Diff line change
@@ -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
#
# -------------------------------------------------------------------------
Loading

0 comments on commit a8cb930

Please sign in to comment.