diff --git a/analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py b/analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py index 4ad42a296e..ed44223560 100644 --- a/analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py +++ b/analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py @@ -138,6 +138,34 @@ def parse_analyzer_config(self): # * -std c99 # * -stdlib=libc++ std_regex = re.compile("-(-std$|-?std=.*)") + + # Mapping is needed, because, if a standard version not known by + # cppcheck is used, then it will assume the latest available version + # before cppcheck-2.15 or fail the analysis from cppcheck-2.15. + # https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#index-std-1 + standard_mapping = { + "c90": "c89", + "c18": "c17", + "iso9899:2017": "c17", + "iso9899:2018": "c17", + "iso9899:1990": "c89", + "iso9899:199409": "c89", # Good enough + "c9x": "c99", + "iso9899:1999": "c99", + "iso9899:199x": "c99", + "c1x": "c11", + "iso9899:2011": "c11", + "c2x": "c23", + "iso9899:2024": "c23", + "c++98": "c++03", + "c++0x": "c++11", + "c++1y": "c++14", + "c++1z": "c++17", + "c++2a": "c++20", + "c++2b": "c++23", + "c++2c": "c++26" + } + for i, analyzer_option in enumerate(self.buildaction.analyzer_options): if interesting_option.match(analyzer_option): params.extend([analyzer_option]) @@ -161,6 +189,7 @@ def parse_analyzer_config(self): else: standard = self.buildaction.analyzer_options[i+1] standard = standard.lower().replace("gnu", "c") + standard = standard_mapping.get(standard, standard) params.extend(["--std=" + standard]) return params diff --git a/analyzer/tests/functional/analyze/test_analyze.py b/analyzer/tests/functional/analyze/test_analyze.py index 88e46ad47c..3b47fa7d93 100644 --- a/analyzer/tests/functional/analyze/test_analyze.py +++ b/analyzer/tests/functional/analyze/test_analyze.py @@ -1083,7 +1083,7 @@ def test_cppcheck_standard(self): stdout=subprocess.PIPE).stdout.decode() # Test correct handover. - self.assertTrue("--std=c99" in out) + self.assertIn("--std=c99", out) # Cppcheck does not support gnu variants of the standards, # These are transformed into their respective c and c++ @@ -1104,7 +1104,25 @@ def test_cppcheck_standard(self): stdout=subprocess.PIPE).stdout.decode() # Test if the standard is correctly transformed - self.assertTrue("--std=c99" in out) + self.assertIn("--std=c99", out) + + build_log = [{"directory": self.test_workspace, + "command": "gcc -c -std=iso9899:2017 " + source_file, + "file": source_file + }] + + with open(build_json, 'w', + encoding="utf-8", errors="ignore") as outfile: + json.dump(build_log, outfile) + + out = subprocess.run(analyze_cmd, + cwd=self.test_dir, + # env=self.env, + check=False, + stdout=subprocess.PIPE).stdout.decode() + + self.assertNotIn("iso9899:2017", out) + self.assertIn("--std=c17", out) def test_makefile_generation(self): """ Test makefile generation. """