• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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