Skip to content

Commit

Permalink
[analyzer] Fix uniqueing compilation commands
Browse files Browse the repository at this point in the history
We are storing unique compilation actions in a map which uses the overriden
`__hash__` and `__eq__` methods on the `BuildAction` class.

For this we used the following logic:

```py
if action.__hash__ not in uniqued_build_actions:
    uniqued_build_actions[action.__hash__] = action
```

In this case we didn't called the function but we checked whether the
function is in the map. Before `Python 3.9` this solution somehow worked
but in later Python versions it will not unique compilation actions properly.

To solve this problem we will use the following logic:

```py
if action not in uniqued_build_actions:
    uniqued_build_actions[action] = action
```

Under the hood the Python interpreter will call the overriden dunder functions.
  • Loading branch information
csordasmarton committed Mar 24, 2022
1 parent 5adc515 commit b15592a
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 11 deletions.
4 changes: 2 additions & 2 deletions analyzer/codechecker_analyzer/buildlog/log_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1297,8 +1297,8 @@ def parse_unique_log(compilation_database,
if action.action_type != BuildAction.COMPILE:
continue
if build_action_uniqueing == CompileActionUniqueingType.NONE:
if action.__hash__ not in uniqued_build_actions:
uniqued_build_actions[action.__hash__] = action
if action not in uniqued_build_actions:
uniqued_build_actions[action] = action
elif build_action_uniqueing == CompileActionUniqueingType.STRICT:
if action.source not in uniqued_build_actions:
uniqued_build_actions[action.source] = action
Expand Down
2 changes: 1 addition & 1 deletion analyzer/codechecker_analyzer/cmd/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ def add_arguments_to_parser(parser):
"compilation target. "
"If none of the above given, "
"this parameter should "
"be a python regular expression."
"be a python regular expression. "
"If there is more than one compilation action "
"for a source, "
"only the one is kept which matches the "
Expand Down
2 changes: 1 addition & 1 deletion analyzer/codechecker_analyzer/cmd/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ def add_arguments_to_parser(parser):
"compilation target. "
"If none of the above given, "
"this parameter should "
"be a python regular expression."
"be a python regular expression. "
"If there is more than one compilation action "
"for a source, "
"only the one is kept which matches the "
Expand Down
24 changes: 19 additions & 5 deletions analyzer/tests/functional/analyze/test_analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,10 +608,20 @@ def test_tidyargs_saargs(self):

self.assertIn("Dereference of null pointer", out)

def unique_json_helper(self, unique_json, is_a, is_b, is_s):
with open(unique_json,
def check_unique_compilation_db(
self,
compilation_db_file_path: str,
num_of_compile_commands: int,
is_a: bool,
is_b: bool,
is_s: bool
):
""" """
with open(compilation_db_file_path,
encoding="utf-8", errors="ignore") as json_file:
data = json.load(json_file)
self.assertEqual(len(data), num_of_compile_commands)

simple_a = False
simple_b = False
success = False
Expand Down Expand Up @@ -646,6 +656,10 @@ def test_compile_uniqueing(self):
"command": "cc -c " + source_file +
" -Iincludes -o simple_a.o",
"file": source_file},
{"directory": self.test_dir,
"command": "cc -c " + source_file +
" -Iincludes -o simple_a.o",
"file": source_file},
{"directory": self.test_dir,
"command": "cc -c " + source_file2 +
" -Iincludes -o success.o",
Expand Down Expand Up @@ -673,7 +687,7 @@ def test_compile_uniqueing(self):
self.assertEqual(errcode, 0)
self.assertFalse(os.path.isdir(failed_dir))

self.unique_json_helper(unique_json, True, False, True)
self.check_unique_compilation_db(unique_json, 2, True, False, True)

# Testing regex mode.
analyze_cmd = [self._codechecker_cmd, "analyze", build_json,
Expand All @@ -692,7 +706,7 @@ def test_compile_uniqueing(self):
self.assertEqual(errcode, 0)
self.assertFalse(os.path.isdir(failed_dir))

self.unique_json_helper(unique_json, False, True, True)
self.check_unique_compilation_db(unique_json, 2, False, True, True)

# Testing regex mode.error handling
analyze_cmd = [self._codechecker_cmd, "analyze", build_json,
Expand Down Expand Up @@ -748,7 +762,7 @@ def test_compile_uniqueing(self):
errcode = process.returncode
self.assertEqual(errcode, 0)
self.assertFalse(os.path.isdir(failed_dir))
self.unique_json_helper(unique_json, True, True, True)
self.check_unique_compilation_db(unique_json, 3, True, True, True)

def test_invalid_enabled_checker_name(self):
"""Warn in case of an invalid enabled checker."""
Expand Down
4 changes: 2 additions & 2 deletions docs/analyzer/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ optional arguments:
compilation action for a source file, only the one is
kept that belongs to the alphabetically first
compilation target. If none of the above given, this
parameter should be a python regular expression.If
parameter should be a python regular expression. If
there is more than one compilation action for a
source, only the one is kept which matches the given
python regex. If more than one matches an error is
Expand Down Expand Up @@ -916,7 +916,7 @@ optional arguments:
compilation action for a source file, only the one is
kept that belongs to the alphabetically first
compilation target. If none of the above given, this
parameter should be a python regular expression.If
parameter should be a python regular expression. If
there is more than one compilation action for a
source, only the one is kept which matches the given
python regex. If more than one matches an error is
Expand Down

0 comments on commit b15592a

Please sign in to comment.