diff options
author | Pierre Moreau <dev@pmoreau.org> | 2018-04-26 18:41:23 +0200 |
---|---|---|
committer | Alexey Sotkin <alexey.sotkin@intel.com> | 2018-06-09 15:32:48 +0300 |
commit | 72d4a32009a5297895ea03cfd4339128039b5669 (patch) | |
tree | c478c67cfa2b146d0606212c68a829ce661802a0 | |
parent | 06888bdfcbe8501d2c894021901355dbadddc9a1 (diff) |
Run clang-tidy on the codebase
-rw-r--r-- | .travis.yml | 9 | ||||
-rwxr-xr-x | utils/check_code_tidyness.sh | 54 | ||||
-rw-r--r-- | utils/clang-tidy-diff.py | 149 |
3 files changed, 212 insertions, 0 deletions
diff --git a/.travis.yml b/.travis.yml index bc3de64..626080e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,7 @@ addons: - llvm-7-tools - llvm-7-dev - clang-format-7 + - clang-tidy-7 compiler: - gcc @@ -33,6 +34,7 @@ env: global: - MAKEFLAGS="-j2" - CHECK_FORMAT=0 + - CHECK_TIDY=0 matrix: - BUILD_TYPE=Release BUILD_EXTERNAL=1 SHARED_LIBS=ON MAKE_TARGETS="" MAKE_TEST_TARGET="test" - BUILD_TYPE=Debug BUILD_EXTERNAL=1 SHARED_LIBS=ON MAKE_TARGETS="" MAKE_TEST_TARGET="test" @@ -55,6 +57,8 @@ matrix: osx_image: xcode9.3 - env: BUILD_EXTERNAL=1 CHECK_FORMAT=1 + + - env: BUILD_EXTERNAL=1 CHECK_TIDY=1 allow_failures: - compiler: clang - os: osx @@ -79,6 +83,7 @@ script: -DLLVM_EXTERNAL_LIT="/usr/lib/llvm-7/build/utils/lit/lit.py" \ -DLLVM_INCLUDE_TESTS=ON \ -DCMAKE_INSTALL_PREFIX=../install/ \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -G "Unix Makefiles" fi else @@ -95,6 +100,10 @@ script: cd ..; ln -s /usr/share/clang/clang-format-7/clang-format-diff.py utils/; ./utils/check_code_format.sh; + elif [ $CHECK_TIDY == "1" ]; then + cd ..; + ln -s build/compile_commands.json; + ./utils/check_code_tidyness.sh; else make $MAKE_TARGETS && make $MAKE_TEST_TARGET && if [ $BUILD_EXTERNAL == "1" ]; then make install; fi fi diff --git a/utils/check_code_tidyness.sh b/utils/check_code_tidyness.sh new file mode 100755 index 0000000..400e930 --- /dev/null +++ b/utils/check_code_tidyness.sh @@ -0,0 +1,54 @@ +#===- SPIRVBasicBlock.cpp - SPIR-V Basic Block ------------------*- Bash -*-===# +# +# The LLVM/SPIRV Translator +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +# Copyright (c) 2018 Pierre Moreau All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal with the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimers. +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimers in the documentation +# and/or other materials provided with the distribution. +# Neither the names of Advanced Micro Devices, Inc., nor the names of its +# contributors may be used to endorse or promote products derived from this +# Software without specific prior written permission. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH +# THE SOFTWARE. +# +#===------------------------------------------------------------------------===# + +MODIFIED_FILES=$(git diff --name-only master | grep -E ".*\.(cpp|cc|c\+\+|cxx|c|h|hpp)$") +FILES_TO_CHECK=$(echo "${MODIFIED_FILES}" | grep -v -E "Mangler/*|runtime/*|libSPIRV/(OpenCL.std.h|spirv.hpp)$") +CPP_FILES=$(find . -regex "\./\(lib\|tools\)/.*\.cpp" | grep -v -E "Mangler/*|runtime/*") +CPP_FILES="${CPP_FILES//$'\n'/ }" + +if [ -z "${FILES_TO_CHECK}" ]; then + echo "No source code to check for tidying." + exit 0 +fi + +TIDY_DIFF=$(git diff -U0 master -- ${FILES_TO_CHECK} | python ./utils/clang-tidy-diff.py -p1 -- "${CPP_FILES}" 2> /dev/null) + +if [ -z "${TIDY_DIFF}" ]; then + echo "All source code in PR properly tidied." + exit 0 +else + echo "Found tidying errors!" + echo "${TIDY_DIFF}" + exit 1 +fi diff --git a/utils/clang-tidy-diff.py b/utils/clang-tidy-diff.py new file mode 100644 index 0000000..fb21958 --- /dev/null +++ b/utils/clang-tidy-diff.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python2 +# +#===- clang-tidy-diff.py - ClangTidy Diff Checker ------------*- python -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +# Changes made to the initial version from +# https://llvm.org/svn/llvm-project/clang-tools-extra: +# * Do not run the test on the files modified by the patch, but on all the +# files specified on the command-line; +# * Set the header-filter to all header files; +# * Remove the "--" when forwarding the input files to clang-tidy. + +r""" +ClangTidy Diff Checker +====================== + +This script reads input from a unified diff, runs clang-tidy on all specified +files and outputs clang-tidy warnings in changed lines only. This is useful to +detect clang-tidy regressions in the lines touched by a specific patch. +Example usage for git/svn users: + + git diff -U0 HEAD^ | clang-tidy-diff.py -p1 -- <source0> [... <sourceN>] + svn diff --diff-cmd=diff -x-U0 | \ + clang-tidy-diff.py -fix -checks=-*,modernize-use-override \ + <source0> [... <sourceN>] + +""" + +import argparse +import json +import re +import subprocess +import sys + + +def main(): + parser = argparse.ArgumentParser(description= + 'Run clang-tidy against specified files, and ' + 'output diagnostics only for modified ' + 'lines.') + parser.add_argument('-clang-tidy-binary', metavar='PATH', + default='clang-tidy', + help='path to clang-tidy binary') + parser.add_argument('-p', metavar='NUM', default=0, + help='strip the smallest prefix containing P slashes') + parser.add_argument('-regex', metavar='PATTERN', default=None, + help='custom pattern selecting file paths to check ' + '(case sensitive, overrides -iregex)') + parser.add_argument('-iregex', metavar='PATTERN', default= + r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)', + help='custom pattern selecting file paths to check ' + '(case insensitive, overridden by -regex)') + + parser.add_argument('-fix', action='store_true', default=False, + help='apply suggested fixes') + parser.add_argument('-checks', + help='checks filter, when not specified, use clang-tidy ' + 'default', + default='') + parser.add_argument('-path', dest='build_path', + help='Path used to read a compile command database.') + parser.add_argument('-extra-arg', dest='extra_arg', + action='append', default=[], + help='Additional argument to append to the compiler ' + 'command line.') + parser.add_argument('-extra-arg-before', dest='extra_arg_before', + action='append', default=[], + help='Additional argument to prepend to the compiler ' + 'command line.') + parser.add_argument('-quiet', action='store_true', default=False, + help='Run clang-tidy in quiet mode') + clang_tidy_args = [] + argv = sys.argv[1:] + if '--' in argv: + clang_tidy_args.extend(argv[argv.index('--')+1:]) + argv = argv[:argv.index('--')] + + args = parser.parse_args(argv) + + # Extract changed lines for each file. + filename = None + lines_by_file = {} + for line in sys.stdin: + match = re.search('^\+\+\+\ \"?(.*?/){%s}([^ \t\n\"]*)' % args.p, line) + if match: + filename = match.group(2) + if filename == None: + continue + + if args.regex is not None: + if not re.match('^%s$' % args.regex, filename): + continue + else: + if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE): + continue + + match = re.search('^@@.*\+(\d+)(,(\d+))?', line) + if match: + start_line = int(match.group(1)) + line_count = 1 + if match.group(3): + line_count = int(match.group(3)) + if line_count == 0: + continue + end_line = start_line + line_count - 1; + lines_by_file.setdefault(filename, []).append([start_line, end_line]) + + if len(lines_by_file) == 0: + print("No relevant changes found.") + sys.exit(0) + + line_filter_json = json.dumps( + [{"name" : name, "lines" : lines_by_file[name]} for name in lines_by_file], + separators = (',', ':')) + + quote = ""; + if sys.platform == 'win32': + line_filter_json=re.sub(r'"', r'"""', line_filter_json) + else: + quote = "'"; + + # Run clang-tidy on files containing changes. + command = [args.clang_tidy_binary] + command.append('-line-filter=' + quote + line_filter_json + quote) + command.append('-header-filter=' + quote + '.*' + quote) + if args.fix: + command.append('-fix') + if args.checks != '': + command.append('-checks=' + quote + args.checks + quote) + if args.quiet: + command.append('-quiet') + if args.build_path is not None: + command.append('-p=%s' % args.build_path) + for arg in args.extra_arg: + command.append('-extra-arg=%s' % arg) + for arg in args.extra_arg_before: + command.append('-extra-arg-before=%s' % arg) + command.extend(clang_tidy_args) + + sys.exit(subprocess.call(' '.join(command), shell=True)) + +if __name__ == '__main__': + main() |