162306a36Sopenharmony_ci#!/usr/bin/env python3 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci# 462306a36Sopenharmony_ci# Copyright (C) Google LLC, 2020 562306a36Sopenharmony_ci# 662306a36Sopenharmony_ci# Author: Nathan Huckleberry <nhuck@google.com> 762306a36Sopenharmony_ci# 862306a36Sopenharmony_ci"""A helper routine run clang-tidy and the clang static-analyzer on 962306a36Sopenharmony_cicompile_commands.json. 1062306a36Sopenharmony_ci""" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciimport argparse 1362306a36Sopenharmony_ciimport json 1462306a36Sopenharmony_ciimport multiprocessing 1562306a36Sopenharmony_ciimport subprocess 1662306a36Sopenharmony_ciimport sys 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cidef parse_arguments(): 2062306a36Sopenharmony_ci """Set up and parses command-line arguments. 2162306a36Sopenharmony_ci Returns: 2262306a36Sopenharmony_ci args: Dict of parsed args 2362306a36Sopenharmony_ci Has keys: [path, type] 2462306a36Sopenharmony_ci """ 2562306a36Sopenharmony_ci usage = """Run clang-tidy or the clang static-analyzer on a 2662306a36Sopenharmony_ci compilation database.""" 2762306a36Sopenharmony_ci parser = argparse.ArgumentParser(description=usage) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci type_help = "Type of analysis to be performed" 3062306a36Sopenharmony_ci parser.add_argument("type", 3162306a36Sopenharmony_ci choices=["clang-tidy", "clang-analyzer"], 3262306a36Sopenharmony_ci help=type_help) 3362306a36Sopenharmony_ci path_help = "Path to the compilation database to parse" 3462306a36Sopenharmony_ci parser.add_argument("path", type=str, help=path_help) 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci return parser.parse_args() 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cidef init(l, a): 4062306a36Sopenharmony_ci global lock 4162306a36Sopenharmony_ci global args 4262306a36Sopenharmony_ci lock = l 4362306a36Sopenharmony_ci args = a 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cidef run_analysis(entry): 4762306a36Sopenharmony_ci # Disable all checks, then re-enable the ones we want 4862306a36Sopenharmony_ci checks = [] 4962306a36Sopenharmony_ci checks.append("-checks=-*") 5062306a36Sopenharmony_ci if args.type == "clang-tidy": 5162306a36Sopenharmony_ci checks.append("linuxkernel-*") 5262306a36Sopenharmony_ci else: 5362306a36Sopenharmony_ci checks.append("clang-analyzer-*") 5462306a36Sopenharmony_ci checks.append("-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling") 5562306a36Sopenharmony_ci p = subprocess.run(["clang-tidy", "-p", args.path, ",".join(checks), entry["file"]], 5662306a36Sopenharmony_ci stdout=subprocess.PIPE, 5762306a36Sopenharmony_ci stderr=subprocess.STDOUT, 5862306a36Sopenharmony_ci cwd=entry["directory"]) 5962306a36Sopenharmony_ci with lock: 6062306a36Sopenharmony_ci sys.stderr.buffer.write(p.stdout) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cidef main(): 6462306a36Sopenharmony_ci try: 6562306a36Sopenharmony_ci args = parse_arguments() 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci lock = multiprocessing.Lock() 6862306a36Sopenharmony_ci pool = multiprocessing.Pool(initializer=init, initargs=(lock, args)) 6962306a36Sopenharmony_ci # Read JSON data into the datastore variable 7062306a36Sopenharmony_ci with open(args.path, "r") as f: 7162306a36Sopenharmony_ci datastore = json.load(f) 7262306a36Sopenharmony_ci pool.map(run_analysis, datastore) 7362306a36Sopenharmony_ci except BrokenPipeError: 7462306a36Sopenharmony_ci # Python flushes standard streams on exit; redirect remaining output 7562306a36Sopenharmony_ci # to devnull to avoid another BrokenPipeError at shutdown 7662306a36Sopenharmony_ci devnull = os.open(os.devnull, os.O_WRONLY) 7762306a36Sopenharmony_ci os.dup2(devnull, sys.stdout.fileno()) 7862306a36Sopenharmony_ci sys.exit(1) # Python exits with error code 1 on EPIPE 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciif __name__ == "__main__": 8262306a36Sopenharmony_ci main() 83