From 9f38b006e9466c06cc25e47042fb84af832e0cfe Mon Sep 17 00:00:00 2001 From: Daniel Krupp Date: Fri, 27 Oct 2023 10:39:21 +0200 Subject: [PATCH] [report-converter] Support Clang 17.0+ FixIt in Clang-Tidy (#4052) Clang-Tidy version 17.0 introduced a new FixIt diagnostic formatting. The report converter is now prepared to parse this new format. It also still supports the old format. Co-Authored-By: Whisperity --- .../analyzers/clang_tidy/parser.py | 28 +++++++++++++++---- .../unit/analyzers/test_clang_tidy_parser.py | 5 ++++ .../tidy_output_test_files/tidy3-clang17.out | 25 +++++++++++++++++ 3 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 tools/report-converter/tests/unit/analyzers/tidy_output_test_files/tidy3-clang17.out diff --git a/tools/report-converter/codechecker_report_converter/analyzers/clang_tidy/parser.py b/tools/report-converter/codechecker_report_converter/analyzers/clang_tidy/parser.py index ade28393bf..5ab1a2de48 100644 --- a/tools/report-converter/codechecker_report_converter/analyzers/clang_tidy/parser.py +++ b/tools/report-converter/codechecker_report_converter/analyzers/clang_tidy/parser.py @@ -55,6 +55,16 @@ def __init__(self): # Checker message. r'(?P.*)') + # Matches pre Clang 17 fix-its: + # " fixit-text" + self.fixit_old_re = re.compile( + r'^\s+(?P\S.*)') + + # Matches post clang 17 fix-its + # " 28 | fixit-text" + self.fixit_new_re = re.compile( + r'^\s*\d*\s*\|\s*(?P\S.*)') + def _parse_line( self, it: Iterator[str], @@ -137,15 +147,23 @@ def _parse_fixits( while self.message_line_re.match(line) is None and \ self.note_line_re.match(line) is None: - message_text = line.strip() + match = self.fixit_new_re.match(line) + if not match: + match = self.fixit_old_re.match(line) + message_text = match.group("message") + # Until Clang 16, the FixIt line starts with whitespace. + col = line.find(message_text) + 1 + else: + message_text = match.group("message") + # In newer versions, we have whitespace then, optionally + # a line number, and then a | character. + col = line.find(message_text) - line.find("|") - 1 - if message_text != '': - report.bug_path_events.append(BugPathEvent( + report.bug_path_events.append(BugPathEvent( f"{message_text} (fixit)", report.file, report.line, - line.find(message_text) + 1)) - + col)) line = next(it) return line diff --git a/tools/report-converter/tests/unit/analyzers/test_clang_tidy_parser.py b/tools/report-converter/tests/unit/analyzers/test_clang_tidy_parser.py index 0f0cf4be32..8d79a3e1f1 100644 --- a/tools/report-converter/tests/unit/analyzers/test_clang_tidy_parser.py +++ b/tools/report-converter/tests/unit/analyzers/test_clang_tidy_parser.py @@ -103,3 +103,8 @@ def test_tidy3(self): self.__check_analyzer_result('tidy3.out', 'test3.hh_clang-tidy.plist', ['files/test3.cpp', 'files/test3.hh'], 'tidy3_hh.plist') + + self.__check_analyzer_result('tidy3-clang17.out', + 'test3.hh_clang-tidy.plist', + ['files/test3.cpp', 'files/test3.hh'], + 'tidy3_hh.plist') diff --git a/tools/report-converter/tests/unit/analyzers/tidy_output_test_files/tidy3-clang17.out b/tools/report-converter/tests/unit/analyzers/tidy_output_test_files/tidy3-clang17.out new file mode 100644 index 0000000000..446eb1fd9c --- /dev/null +++ b/tools/report-converter/tests/unit/analyzers/tidy_output_test_files/tidy3-clang17.out @@ -0,0 +1,25 @@ +files/test3.hh:6:6: warning: Dereference of null pointer (loaded from variable 'x') [clang-analyzer-core.NullDereference] + 6 | *x = 42; + | ^ +files/test3.cpp:4:3: note: 'x' initialized to a null pointer value + 4 | int* x = 0; + | ^~~~~~ +files/test3.cpp:6:11: note: Assuming 'argc' is > 3 + 6 | if (foo(argc > 3)) { + | ^~~~~~~~ +files/test3.cpp:6:3: note: Taking true branch + 6 | if (foo(argc > 3)) { + | ^ +files/test3.cpp:7:9: note: Passing null pointer value via 1st parameter 'x' + 7 | bar(x); + | ^ +files/test3.cpp:7:5: note: Calling 'bar' + 7 | bar(x); + | ^~~~~~ +files/test3.hh:6:6: note: Dereference of null pointer (loaded from variable 'x') + 6 | *x = 42; + | ~ ^ +files/test3.cpp:4:12: warning: use nullptr [modernize-use-nullptr] + 4 | int* x = 0; + | ^ + | nullptr \ No newline at end of file