Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions analyzer/codechecker_analyzer/analyzers/gcc/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@

from .config_handler import GccConfigHandler
from .result_handler import GccResultHandler, \
actual_name_to_codechecker_name, codechecker_name_to_actual_name_disabled
actual_name_to_codechecker_name, \
codechecker_name_to_actual_name, codechecker_name_to_actual_name_disabled

LOG = get_logger('analyzer.gcc')

Expand Down Expand Up @@ -77,6 +78,9 @@ def construct_analyzer_cmd(self, result_handler):
# than startswith and a hardcoded slicing
analyzer_cmd.append(
codechecker_name_to_actual_name_disabled(checker_name))
else:
analyzer_cmd.append(
codechecker_name_to_actual_name(checker_name))

compile_lang = self.buildaction.lang
if not has_flag('-x', analyzer_cmd):
Expand Down Expand Up @@ -106,17 +110,27 @@ def get_analyzer_checkers(cls):
try:
output = subprocess.check_output(command, env=environ)

context = analyzer_context.get_context()

blacklisted_checkers = context.checker_labels.checkers_by_labels(
["blacklist:true"], cls.ANALYZER_NAME)

# Still contains the help message we need to remove.
for entry in output.decode().split('\n'):
warning_name, _, description = entry.strip().partition(' ')
# GCC Static Analyzer names start with -Wanalyzer.
if warning_name.startswith('-Wanalyzer'):
# Rename the checkers interally (similarly to how we
# support cppcheck)
renamed_checker_name = \
actual_name_to_codechecker_name(warning_name)
checker_list.append(
(renamed_checker_name, description.strip()))
# We filter out the unwanted checkers
if not warning_name.startswith('-W') or '=' in warning_name \
or warning_name == '-W' \
or actual_name_to_codechecker_name(warning_name) \
in blacklisted_checkers:
continue
# GCC Static Analyzer names and warning names start with -W.
# Rename the checkers interally
# (similarly to how we support cppcheck)
renamed_checker_name = \
actual_name_to_codechecker_name(warning_name)
checker_list.append(
(renamed_checker_name, description.strip()))
return checker_list
except (subprocess.CalledProcessError) as e:
LOG.error(e.stderr)
Expand Down
14 changes: 11 additions & 3 deletions analyzer/codechecker_analyzer/analyzers/gcc/result_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,25 @@


def actual_name_to_codechecker_name(actual_name: str):
assert actual_name.startswith('-Wanalyzer')
return actual_name.replace("-Wanalyzer", "gcc")
assert actual_name.startswith('-W')
if actual_name.startswith('-Wanalyzer'):
return actual_name.replace("-Wanalyzer", "gcc")
else:
return actual_name.replace("-W", "gcc-diagnostic-")


def codechecker_name_to_actual_name(codechecker_name: str):
assert codechecker_name.startswith('gcc')
return codechecker_name.replace("gcc", "-Wanalyzer")
if codechecker_name.startswith('gcc-diagnostic-'):
return codechecker_name.replace("gcc-diagnostic-", "-W")
else:
return codechecker_name.replace("gcc", "-Wanalyzer")


def codechecker_name_to_actual_name_disabled(codechecker_name: str):
assert codechecker_name.startswith('gcc')
if codechecker_name.startswith('gcc-diagnostic-'):
return codechecker_name.replace("gcc-diagnostic-", "-Wno-")
return codechecker_name.replace("gcc", "-Wno-analyzer")


Expand Down
99 changes: 99 additions & 0 deletions analyzer/tests/functional/analyze/test_analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,105 @@ def test_disable_all_checkers(self):
# Checkers of all 3 analyzers are disabled.
self.assertEqual(out.count("No checkers enabled for"), 5)

def test_analyzer_gcc_warnings(self):
build_json = os.path.join(self.test_workspace, "build.json")
source_file = os.path.join(self.test_dir, "compiler_warning.c")

build_log = [{"directory": self.test_workspace,
"command": "gcc -c " + source_file, "file": source_file}]

with open(build_json, 'w',
encoding="utf-8", errors="ignore") as outfile:
json.dump(build_log, outfile)

analyze_cmd = [self._codechecker_cmd, "analyze", build_json,
"--analyzers", "gcc",
"-o", self.report_dir,
"--disable-all",
"--verbose", "debug_analyzer"]

process = subprocess.Popen(
analyze_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=self.test_dir,
encoding="utf-8",
errors="ignore")
out, _ = process.communicate()
self.assertEqual(out.count("No checkers enabled for gcc"), 1)

analyze_cmd = [self._codechecker_cmd, "analyze", build_json,
"--analyzers", "gcc",
"-o", self.report_dir,
"--enable", "gcc-diagnostic-div-by-zero",
"--verbose", "debug_analyzer"]

process = subprocess.Popen(
analyze_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=self.test_dir,
encoding="utf-8",
errors="ignore")
out, _ = process.communicate()
self.assertEqual(out.count("gcc: 1"), 1)
self.assertEqual(out.count("Wdiv-by-zero"), 2)

analyze_cmd = [self._codechecker_cmd, "analyze", build_json,
"--analyzers", "gcc",
"-o", self.report_dir,
"--enable", "gcc-out-of-bounds",
"--verbose", "debug_analyzer"]

process = subprocess.Popen(
analyze_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=self.test_dir,
encoding="utf-8",
errors="ignore")
out, _ = process.communicate()
self.assertEqual(out.count("gcc: 1"), 1)
self.assertEqual(out.count("Wanalyzer-out-of-bounds"), 2)

analyze_cmd = [self._codechecker_cmd, "analyze", build_json,
"--analyzers", "gcc",
"-o", self.report_dir,
"--enable", "gcc-diagnostic-comment",
"--verbose", "debug_analyzer"]

process = subprocess.Popen(
analyze_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=self.test_dir,
encoding="utf-8",
errors="ignore")
out, _ = process.communicate()
self.assertEqual(out.count("gcc: 1"), 1)
self.assertEqual(out.count("Wcomment"), 2)

analyze_cmd = [self._codechecker_cmd, "analyze", build_json,
"--analyzers", "gcc",
"-o", self.report_dir,
"--enable-all",
"--disable", "gcc-diagnostic-div-by-zero",
"--disable", "gcc-out-of-bounds",
"--disable", "gcc-diagnostic-comment",
"--verbose", "debug_analyzer"]

process = subprocess.Popen(
analyze_cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=self.test_dir,
encoding="utf-8",
errors="ignore")
out, _ = process.communicate()
self.assertEqual(out.count("Wno-div-by-zero"), 2)
self.assertEqual(out.count("Wno-analyzer-out-of-bounds"), 2)
self.assertEqual(out.count("Wno-comment"), 2)

def test_analyzer_and_checker_config(self):
"""Test analyzer configuration through command line flags."""
build_json = os.path.join(self.test_workspace, "build_success.json")
Expand Down
2 changes: 1 addition & 1 deletion analyzer/tests/unit/test_checker_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,7 @@ def create_analyzer_cppcheck(args, workspace):


class MockCppcheckCheckerLabels:
def checkers_by_labels(self, labels):
def checkers_by_labels(self, labels, _=None):
if labels[0] == 'profile:default':
return [
'cppcheck-argumentSize',
Expand Down
Loading
Loading