1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright 2017 The Chromium Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7"""Adds an analysis build step to invocations of the Clang C/C++ compiler. 8 9Usage: clang_static_analyzer_wrapper.py <compiler> [args...] 10""" 11 12import argparse 13import sys 14import wrapper_utils 15 16# Flags used to enable analysis for Clang invocations. 17analyzer_enable_flags = [ 18 '--analyze', 19] 20 21# Flags used to configure the analyzer's behavior. 22analyzer_option_flags = [ 23 '-fdiagnostics-show-option', 24 '-analyzer-checker=cplusplus', 25 '-analyzer-opt-analyze-nested-blocks', 26 '-analyzer-eagerly-assume', 27 '-analyzer-output=text', 28 '-analyzer-config', 29 'suppress-c++-stdlib=true', 30 31 # List of checkers to execute. 32 # The full list of checkers can be found at 33 # https://clang-analyzer.llvm.org/available_checks.html. 34 '-analyzer-checker=core', 35 '-analyzer-checker=unix', 36 '-analyzer-checker=deadcode', 37] 38 39 40# Prepends every element of a list |args| with |token|. 41# e.g. ['-analyzer-foo', '-analyzer-bar'] => ['-Xanalyzer', '-analyzer-foo', 42# '-Xanalyzer', '-analyzer-bar'] 43def interleave_args(args, token): 44 return list(sum(zip([token] * len(args), args), ())) 45 46 47def main(): 48 parser = argparse.ArgumentParser() 49 parser.add_argument('--mode', 50 choices=['clang', 'cl'], 51 required=True, 52 help='Specifies the compiler argument convention ' 53 'to use.') 54 parser.add_argument('args', nargs=argparse.REMAINDER) 55 parsed_args = parser.parse_args() 56 57 prefix = '-Xclang' if parsed_args.mode == 'cl' else '-Xanalyzer' 58 cmd = parsed_args.args + analyzer_enable_flags + interleave_args( 59 analyzer_option_flags, prefix) 60 returncode, stderr = wrapper_utils.capture_command_stderr( 61 wrapper_utils.command_to_run(cmd)) 62 sys.stderr.write(stderr) 63 64 return_code, stderr = wrapper_utils.capture_command_stderr( 65 wrapper_utils.command_to_run(parsed_args.args)) 66 sys.stderr.write(stderr) 67 68 return return_code 69 70 71if __name__ == '__main__': 72 sys.exit(main()) 73