3 # ===- check-analyzer-fixit.py - Static Analyzer test helper ---*- python -*-===#
5 # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6 # See https://llvm.org/LICENSE.txt for license information.
7 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
9 # ===------------------------------------------------------------------------===#
11 # This file copy-pasted mostly from the Clang-Tidy's 'check_clang_tidy.py'.
13 # ===------------------------------------------------------------------------===#
16 Clang Static Analyzer test helper
17 =================================
19 This script runs the Analyzer in fix-it mode and verify fixes, warnings, notes.
22 check-analyzer-fixit.py <source-file> <temp-file> [analyzer arguments]
25 // RUN: %check-analyzer-fixit %s %t -analyzer-checker=core
35 def write_file(file_name
, text
):
36 with
open(file_name
, "w") as f
:
40 def run_test_once(args
, extra_args
):
41 input_file_name
= args
.input_file_name
42 temp_file_name
= args
.temp_file_name
43 clang_analyzer_extra_args
= extra_args
45 file_name_with_extension
= input_file_name
46 _
, extension
= os
.path
.splitext(file_name_with_extension
)
47 if extension
not in [".c", ".hpp", ".m", ".mm"]:
49 temp_file_name
= temp_file_name
+ extension
51 with
open(input_file_name
, "r") as input_file
:
52 input_text
= input_file
.read()
54 # Remove the contents of the CHECK lines to avoid CHECKs matching on
55 # themselves. We need to keep the comments to preserve line numbers while
56 # avoiding empty lines which could potentially trigger formatting-related
58 cleaned_test
= re
.sub("// *CHECK-[A-Z0-9\-]*:[^\r\n]*", "//", input_text
)
59 write_file(temp_file_name
, cleaned_test
)
61 original_file_name
= temp_file_name
+ ".orig"
62 write_file(original_file_name
, cleaned_test
)
65 builtin_include_dir
= subprocess
.check_output(
66 ["clang", "-print-file-name=include"], stderr
=subprocess
.STDOUT
68 except subprocess
.CalledProcessError
as e
:
69 print("Cannot print Clang include directory: " + e
.output
.decode())
71 builtin_include_dir
= os
.path
.normpath(builtin_include_dir
)
81 "-analyzer-constraints=range",
85 + clang_analyzer_extra_args
86 + ["-verify", temp_file_name
]
89 print("Running " + str(args
) + "...")
92 clang_analyzer_output
= subprocess
.check_output(
93 args
, stderr
=subprocess
.STDOUT
95 except subprocess
.CalledProcessError
as e
:
96 print("Clang Static Analyzer test failed:\n" + e
.output
.decode())
100 "----------------- Clang Static Analyzer output -----------------\n"
101 + clang_analyzer_output
102 + "\n--------------------------------------------------------------"
106 diff_output
= subprocess
.check_output(
107 ["diff", "-u", original_file_name
, temp_file_name
], stderr
=subprocess
.STDOUT
109 except subprocess
.CalledProcessError
as e
:
110 diff_output
= e
.output
113 "----------------------------- Fixes ----------------------------\n"
114 + diff_output
.decode()
115 + "\n--------------------------------------------------------------"
119 subprocess
.check_output(
122 "-input-file=" + temp_file_name
,
124 "-check-prefixes=CHECK-FIXES",
125 "-strict-whitespace",
127 stderr
=subprocess
.STDOUT
,
129 except subprocess
.CalledProcessError
as e
:
130 print("FileCheck failed:\n" + e
.output
.decode())
135 parser
= argparse
.ArgumentParser()
136 parser
.add_argument("input_file_name")
137 parser
.add_argument("temp_file_name")
139 args
, extra_args
= parser
.parse_known_args()
140 run_test_once(args
, extra_args
)
143 if __name__
== "__main__":