summaryrefslogtreecommitdiff
path: root/clang-r353983/bin/clang-tidy
diff options
context:
space:
mode:
Diffstat (limited to 'clang-r353983/bin/clang-tidy')
-rwxr-xr-xclang-r353983/bin/clang-tidy192
1 files changed, 192 insertions, 0 deletions
diff --git a/clang-r353983/bin/clang-tidy b/clang-r353983/bin/clang-tidy
new file mode 100755
index 00000000..081cb20a
--- /dev/null
+++ b/clang-r353983/bin/clang-tidy
@@ -0,0 +1,192 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# pylint: disable=not-callable, relative-import
+
+# Note that adding top-level imports is discouraged unless they're guaranteed to
+# be used. Unnecessary imports eat a measurable number of cycles of this
+# wrapper.
+import os
+import sys
+
+BISECT_STAGE = os.environ.get('BISECT_STAGE')
+# We do not need bisect functionality with Goma and clang.
+# Goma server does not have bisect_driver, so we only import
+# bisect_driver when needed. See http://b/34862041
+# We should be careful when doing imports because of Goma.
+if BISECT_STAGE:
+ import bisect_driver
+
+DEFAULT_BISECT_DIR = os.path.expanduser('~/ANDROID_BISECT')
+BISECT_DIR = os.environ.get('BISECT_DIR') or DEFAULT_BISECT_DIR
+STDERR_REDIRECT_KEY = 'ANDROID_LLVM_STDERR_REDIRECT'
+PREBUILT_COMPILER_PATH_KEY = 'ANDROID_LLVM_PREBUILT_COMPILER_PATH'
+DISABLED_WARNINGS_KEY = 'ANDROID_LLVM_FALLBACK_DISABLED_WARNINGS'
+
+
+def ProcessArgFile(arg_file):
+ import shlex
+
+ args = []
+ # Read in entire file at once and parse as if in shell
+ with open(arg_file, 'rb') as f:
+ args.extend(shlex.split(f.read()))
+ return args
+
+
+def write_log(path, command, log):
+ import errno
+ import fcntl
+ import time
+
+ with open(path, 'a+') as f:
+ while True:
+ try:
+ fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ break
+ except IOError as e:
+ if e.errno == errno.EAGAIN or e.errno == errno.EACCES:
+ time.sleep(0.5)
+ f.write('==================COMMAND:====================\n')
+ f.write(' '.join(command) + '\n\n')
+ f.write(log)
+ f.write('==============================================\n\n')
+
+
+class CompilerWrapper(object):
+
+ def __init__(self, argv):
+ self.argv0_current = argv[0]
+ self.args = argv[1:]
+ self.execargs = []
+ self.real_compiler = None
+ self.argv0 = None
+ self.append_flags = []
+ self.prepend_flags = []
+ self.custom_flags = {'--gomacc-path': None}
+
+ def set_real_compiler(self):
+ """Find the real compiler with the absolute path."""
+ compiler_path = os.path.dirname(self.argv0_current)
+ if os.path.islink(__file__):
+ compiler = os.path.basename(os.readlink(__file__))
+ else:
+ compiler = os.path.basename(os.path.abspath(__file__))
+ self.real_compiler = os.path.join(compiler_path, compiler + '.real')
+ self.argv0 = self.real_compiler
+
+ def process_gomacc_command(self):
+ """Return the gomacc command if '--gomacc-path' is set."""
+ gomacc = self.custom_flags['--gomacc-path']
+ if gomacc and os.path.isfile(gomacc):
+ self.argv0 = gomacc
+ self.execargs += [gomacc]
+
+ def parse_custom_flags(self):
+ i = 0
+ args = []
+ while i < len(self.args):
+ if self.args[i] in self.custom_flags:
+ if i >= len(self.args) - 1:
+ sys.exit('The value of {} is not set.'.format(self.args[i]))
+ self.custom_flags[self.args[i]] = self.args[i + 1]
+ i = i + 2
+ else:
+ args.append(self.args[i])
+ i = i + 1
+ self.args = args
+
+ def add_flags(self):
+ self.args = self.prepend_flags + self.args + self.append_flags
+
+ def prepare_compiler_args(self, enable_fallback=False):
+ self.set_real_compiler()
+ self.parse_custom_flags()
+ # Goma should not be enabled for new prebuilt.
+ if not enable_fallback:
+ self.process_gomacc_command()
+ self.add_flags()
+ self.execargs += [self.real_compiler] + self.args
+
+ def exec_clang_with_fallback(self):
+ import subprocess
+
+ extra_args_begin = len(self.execargs)
+
+ # We only want to pass extra flags to clang and clang++.
+ if os.path.basename(__file__) in ['clang', 'clang++']:
+ # We may introduce some new warnings after rebasing and we need to
+ # disable them before we fix those warnings.
+ disabled_warnings_env = os.environ.get(DISABLED_WARNINGS_KEY, '')
+ disabled_warnings = disabled_warnings_env.split(' ')
+ self.execargs += ['-fno-color-diagnostics'] + disabled_warnings
+
+ p = subprocess.Popen(self.execargs, stderr=subprocess.PIPE)
+ (_, err) = p.communicate()
+ sys.stderr.write(err)
+ if p.returncode != 0:
+ redirect_path = os.environ[STDERR_REDIRECT_KEY]
+ write_log(redirect_path, self.execargs, err)
+ fallback_arg0 = os.path.join(os.environ[PREBUILT_COMPILER_PATH_KEY],
+ os.path.basename(__file__))
+
+ # Delete PREBUILT_COMPILER_PATH_KEY so the fallback doesn't keep
+ # calling itself in case of an error.
+ del os.environ[PREBUILT_COMPILER_PATH_KEY]
+
+ # Strip extra args added (from DISABLED_WARNINGS_KEY) for clang and
+ # clang++ above. They may not be recognized by the fallback clang.
+ self.execargs = self.execargs[:extra_args_begin]
+
+ os.execv(fallback_arg0, [fallback_arg0] + self.execargs[1:])
+
+ def invoke_compiler(self):
+ enable_fallback = PREBUILT_COMPILER_PATH_KEY in os.environ
+ self.prepare_compiler_args(enable_fallback)
+ if enable_fallback:
+ self.exec_clang_with_fallback()
+ else:
+ os.execv(self.argv0, self.execargs)
+
+ def bisect(self):
+ self.prepare_compiler_args()
+ # Handle @file argument syntax with compiler
+ idx = 0
+ # The length of self.execargs can be changed during the @file argument
+ # expansion, so we need to use while loop instead of for loop.
+ while idx < len(self.execargs):
+ if self.execargs[idx][0] == '@':
+ args_in_file = ProcessArgFile(self.execargs[idx][1:])
+ self.execargs = self.execargs[0:idx] + args_in_file +\
+ self.execargs[idx + 1:]
+ # Skip update of idx, since we want to recursively expand
+ # response files.
+ else:
+ idx = idx + 1
+ bisect_driver.bisect_driver(BISECT_STAGE, BISECT_DIR, self.execargs)
+
+
+def main(argv):
+ cw = CompilerWrapper(argv)
+ if BISECT_STAGE and BISECT_STAGE in bisect_driver.VALID_MODES\
+ and '-o' in argv:
+ cw.bisect()
+ else:
+ cw.invoke_compiler()
+
+
+if __name__ == '__main__':
+ main(sys.argv)