diff --git a/analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py b/analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py index ed44223560..e5d03251a2 100644 --- a/analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py +++ b/analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py @@ -20,6 +20,7 @@ import xml.etree.ElementTree as ET from codechecker_common.logger import get_logger +from codechecker_common import util from codechecker_analyzer import analyzer_context, env from codechecker_analyzer.env import get_binary_in_path @@ -223,7 +224,17 @@ def construct_analyzer_cmd(self, result_handler): analyzer_cmd.extend(config.analyzer_extra_arguments) # Pass whitelisted parameters - analyzer_cmd.extend(self.parse_analyzer_config()) + params = self.parse_analyzer_config() + + def is_std(arg): + return arg.startswith("--std=") + + if util.index_of(config.analyzer_extra_arguments, is_std) >= 0: + std_idx = util.index_of(params, is_std) + if std_idx >= 0: + del params[std_idx] + + analyzer_cmd.extend(params) # TODO fix this in a follow up patch, because it is failing # the macos pypy test. diff --git a/analyzer/tests/functional/analyze/test_analyze.py b/analyzer/tests/functional/analyze/test_analyze.py index 3b47fa7d93..db89acb7bf 100644 --- a/analyzer/tests/functional/analyze/test_analyze.py +++ b/analyzer/tests/functional/analyze/test_analyze.py @@ -18,6 +18,7 @@ import shutil import subprocess import shlex +import tempfile import unittest import zipfile @@ -1124,6 +1125,31 @@ def test_cppcheck_standard(self): self.assertNotIn("iso9899:2017", out) self.assertIn("--std=c17", out) + # Test if standard version in --cppcheckargs is stronger. + with tempfile.NamedTemporaryFile(mode='w', + encoding='utf-8') as cppcheck_args: + with open(build_json, 'w', + encoding="utf-8", errors="ignore") as outfile: + build_log = [{ + "directory": self.test_workspace, + "command": "gcc -c -std=c++0x " + source_file, + "file": source_file}] + json.dump(build_log, outfile) + + cppcheck_args.write("--std=c++11") + cppcheck_args.close() + + analyze_cmd.extend(['--cppcheckargs', cppcheck_args.name]) + + out = subprocess.run(analyze_cmd, + cwd=self.test_dir, + # env=self.env, + check=False, + stdout=subprocess.PIPE).stdout.decode() + + self.assertIn("--std=c++11", out) + self.assertNotIn("--std=c++0x", out) + def test_makefile_generation(self): """ Test makefile generation. """ build_json = os.path.join(self.test_workspace, "build_extra_args.json") diff --git a/codechecker_common/util.py b/codechecker_common/util.py index e389b8d1a0..b71953c753 100644 --- a/codechecker_common/util.py +++ b/codechecker_common/util.py @@ -112,3 +112,14 @@ def path_for_fake_root(full_path: str, root_path: str = '/') -> str: def strtobool(value: str) -> bool: """Parse a string value to a boolean.""" return value.lower() in ('y', 'yes', 't', 'true', 'on', '1') + + +def index_of(iterable, lambda_func) -> int: + """Return the index of the first element in iterable for which + lambda_func returns True. + """ + for i, item in enumerate(iterable): + if lambda_func(item): + return i + + return -1