[clang][NFC] simplify the unset check in `ParseLabeledStatement` (#117430)
[llvm-project.git] / clang / test / Analysis / check-analyzer-fixit.py
blobb616255de89b0cf7e6392a67abd36668fc88b8a9
1 #!/usr/bin/env python
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 # ===------------------------------------------------------------------------===#
15 r"""
16 Clang Static Analyzer test helper
17 =================================
19 This script runs the Analyzer in fix-it mode and verify fixes, warnings, notes.
21 Usage:
22 check-analyzer-fixit.py <source-file> <temp-file> [analyzer arguments]
24 Example:
25 // RUN: %check-analyzer-fixit %s %t -analyzer-checker=core
26 """
28 import argparse
29 import os
30 import re
31 import subprocess
32 import sys
35 def write_file(file_name, text):
36 with open(file_name, "w") as f:
37 f.write(text)
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"]:
48 extension = ".cpp"
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
57 # checks.
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)
64 try:
65 builtin_include_dir = subprocess.check_output(
66 ["clang", "-print-file-name=include"], stderr=subprocess.STDOUT
67 ).decode()
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)
73 args = (
75 "clang",
76 "-cc1",
77 "-internal-isystem",
78 builtin_include_dir,
79 "-nostdsysteminc",
80 "-analyze",
81 "-analyzer-constraints=range",
82 "-analyzer-config",
83 "apply-fixits=true",
85 + clang_analyzer_extra_args
86 + ["-verify", temp_file_name]
89 print("Running " + str(args) + "...")
91 try:
92 clang_analyzer_output = subprocess.check_output(
93 args, stderr=subprocess.STDOUT
94 ).decode()
95 except subprocess.CalledProcessError as e:
96 print("Clang Static Analyzer test failed:\n" + e.output.decode())
97 raise
99 print(
100 "----------------- Clang Static Analyzer output -----------------\n"
101 + clang_analyzer_output
102 + "\n--------------------------------------------------------------"
105 try:
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
112 print(
113 "----------------------------- Fixes ----------------------------\n"
114 + diff_output.decode()
115 + "\n--------------------------------------------------------------"
118 try:
119 subprocess.check_output(
121 "FileCheck",
122 "-input-file=" + temp_file_name,
123 input_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())
131 raise
134 def main():
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__":
144 main()