Bug 1432410 - Add tests in tree to make sure we don't regress with clang-tidy on static-analisys. Tests wrote in part by :sylvestre. r?gps draft
authorAndi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
Thu, 03 May 2018 20:06:16 +0300
changeset 791170 8d19886db5973a30fb5f7037943cc6ae1fc290a0
parent 791136 35165f43d0b97f500dafb4f0f7b9ca8d91416812
push id108720
push userbmo:bpostelnicu@mozilla.com
push dateThu, 03 May 2018 17:19:45 +0000
reviewersgps
bugs1432410
milestone61.0a1
Bug 1432410 - Add tests in tree to make sure we don't regress with clang-tidy on static-analisys. Tests wrote in part by :sylvestre. r?gps MozReview-Commit-ID: IWxzKfWNIHG
python/mozbuild/mozbuild/mach_commands.py
taskcluster/ci/static-analysis-autotest/kind.yml
taskcluster/docs/kinds.rst
testing/mozharness/mozharness/mozilla/building/buildbase.py
testing/mozharness/scripts/fx_desktop_build.py
tools/clang-tidy/config.yaml
tools/clang-tidy/test/clang-analyzer-deadcode.DeadStores.cpp
tools/clang-tidy/test/clang-analyzer-deadcode.DeadStores.json
tools/clang-tidy/test/clang-analyzer-security.FloatLoopCounter.cpp
tools/clang-tidy/test/clang-analyzer-security.FloatLoopCounter.json
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.UncheckedReturn.cpp
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.UncheckedReturn.json
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.getpw.cpp
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.getpw.json
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.gets.cpp
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.gets.json
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.mkstemp.cpp
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.mkstemp.json
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.mktemp.cpp
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.mktemp.json
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.rand.cpp
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.rand.json
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.strcpy.cpp
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.strcpy.json
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.vfork.cpp
tools/clang-tidy/test/clang-analyzer-security.insecureAPI.vfork.json
tools/clang-tidy/test/misc-argument-comment.cpp
tools/clang-tidy/test/misc-argument-comment.json
tools/clang-tidy/test/misc-assert-side-effect.cpp
tools/clang-tidy/test/misc-assert-side-effect.json
tools/clang-tidy/test/misc-forward-declaration-namespace.cpp
tools/clang-tidy/test/misc-forward-declaration-namespace.json
tools/clang-tidy/test/misc-suspicious-missing-comma.cpp
tools/clang-tidy/test/misc-suspicious-missing-comma.json
tools/clang-tidy/test/misc-suspicious-semicolon.cpp
tools/clang-tidy/test/misc-suspicious-semicolon.json
tools/clang-tidy/test/misc-unused-using-decls.cpp
tools/clang-tidy/test/misc-unused-using-decls.json
tools/clang-tidy/test/modernize-avoid-bind.cpp
tools/clang-tidy/test/modernize-avoid-bind.json
tools/clang-tidy/test/modernize-loop-convert.cpp
tools/clang-tidy/test/modernize-loop-convert.json
tools/clang-tidy/test/modernize-raw-string-literal.cpp
tools/clang-tidy/test/modernize-raw-string-literal.json
tools/clang-tidy/test/modernize-redundant-void-arg.cpp
tools/clang-tidy/test/modernize-redundant-void-arg.json
tools/clang-tidy/test/modernize-shrink-to-fit.cpp
tools/clang-tidy/test/modernize-shrink-to-fit.json
tools/clang-tidy/test/modernize-use-auto.cpp
tools/clang-tidy/test/modernize-use-auto.json
tools/clang-tidy/test/modernize-use-bool-literals.cpp
tools/clang-tidy/test/modernize-use-bool-literals.json
tools/clang-tidy/test/modernize-use-equals-default.cpp
tools/clang-tidy/test/modernize-use-equals-default.json
tools/clang-tidy/test/modernize-use-equals-delete.cpp
tools/clang-tidy/test/modernize-use-equals-delete.json
tools/clang-tidy/test/modernize-use-nullptr.cpp
tools/clang-tidy/test/modernize-use-nullptr.json
tools/clang-tidy/test/modernize-use-override.cpp
tools/clang-tidy/test/modernize-use-override.json
tools/clang-tidy/test/performance-faster-string-find.cpp
tools/clang-tidy/test/performance-faster-string-find.json
tools/clang-tidy/test/performance-for-range-copy.cpp
tools/clang-tidy/test/performance-for-range-copy.json
tools/clang-tidy/test/performance-inefficient-string-concatenation.cpp
tools/clang-tidy/test/performance-inefficient-string-concatenation.json
tools/clang-tidy/test/performance-inefficient-vector-operation.cpp
tools/clang-tidy/test/performance-inefficient-vector-operation.json
tools/clang-tidy/test/performance-type-promotion-in-math-fn.cpp
tools/clang-tidy/test/performance-type-promotion-in-math-fn.json
tools/clang-tidy/test/performance-unnecessary-copy-initialization.cpp
tools/clang-tidy/test/performance-unnecessary-copy-initialization.json
tools/clang-tidy/test/performance-unnecessary-value-param.cpp
tools/clang-tidy/test/performance-unnecessary-value-param.json
tools/clang-tidy/test/readability-container-size-empty.cpp
tools/clang-tidy/test/readability-container-size-empty.json
tools/clang-tidy/test/readability-else-after-return.cpp
tools/clang-tidy/test/readability-else-after-return.json
tools/clang-tidy/test/readability-misleading-indentation.cpp
tools/clang-tidy/test/readability-misleading-indentation.json
tools/clang-tidy/test/readability-redundant-control-flow.cpp
tools/clang-tidy/test/readability-redundant-control-flow.json
tools/clang-tidy/test/readability-redundant-smartptr-get.cpp
tools/clang-tidy/test/readability-redundant-smartptr-get.json
tools/clang-tidy/test/readability-redundant-string-cstr.cpp
tools/clang-tidy/test/readability-redundant-string-cstr.json
tools/clang-tidy/test/readability-redundant-string-init.cpp
tools/clang-tidy/test/readability-redundant-string-init.json
tools/clang-tidy/test/readability-uniqueptr-delete-release.cpp
tools/clang-tidy/test/readability-uniqueptr-delete-release.json
tools/clang-tidy/test/structures.h
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -1700,16 +1700,146 @@ class StaticAnalysis(MachCommandBase):
         with StaticAnalysisOutputManager(self.log_manager, monitor, footer) as output:
             rc = self.run_process(args=args, line_handler=output.on_line, cwd=cwd)
 
             self.log(logging.WARNING, 'warning_summary',
                      {'count': len(monitor.warnings_db)},
                      '{count} warnings present.')
             return rc
 
+    @StaticAnalysisSubCommand('static-analysis', 'autotest',
+                              'Run the auto-test suite in order to determine that'
+                              ' the analysis did not regress.')
+    @CommandArgument('--dump-results', '-d', default=False, action='store_true',
+                     help='Generate the baseline for the regression test. Based on'
+                     ' this baseline we will test future results.')
+    @CommandArgument('--intree-tool', '-i', default=False, action='store_true',
+                     help='Use a pre-aquired in-tree clang-tidy package.')
+    @CommandArgument('checker_names', nargs='*', default=[], help='Checkers that are going to be auto-tested.')
+    def autotest(self, verbose=False, dump_results=False, intree_tool=False, checker_names=[]):
+        # If 'dump_results' is True than we just want to generate the issues files for each
+        # checker in particulat and thus 'force_download' becomes 'False' since we want to
+        # do this on a local trusted clang-tidy package.
+        self._set_log_level(verbose)
+        force_download = True
+
+        if dump_results:
+            force_download = False
+
+        # Function return codes
+        TOOLS_SUCCESS = 0
+        TOOLS_FAILED_DOWNLOAD = 1
+        TOOLS_UNSUPORTED_PLATFORM = 2
+        TOOLS_CHECKER_NO_TEST_FILE = 3
+        TOOLS_CHECKER_RETURNED_NO_ISSUES = 4
+        TOOLS_CHECKER_RESULT_FILE_NOT_FOUND = 5
+        TOOLS_CHECKER_DIFF_FAILED = 6
+
+        # Configure the tree or download clang-tidy package, depending on the option that we choose
+        if intree_tool:
+            _, config, _ = self._get_config_environment()
+            clang_tools_path = self.topsrcdir
+            self._clang_tidy_path = mozpath.join(
+                clang_tools_path, "clang", "bin",
+                "clang-tidy" + config.substs.get('BIN_SUFFIX', ''))
+            self._clang_format_path = mozpath.join(
+                clang_tools_path, "clang", "bin",
+                "clang-format" + config.substs.get('BIN_SUFFIX', ''))
+            self._clang_apply_replacements = mozpath.join(
+                clang_tools_path, "clang", "bin",
+                "clang-apply-replacements" + config.substs.get('BIN_SUFFIX', ''))
+            self._run_clang_tidy_path = mozpath.join(clang_tools_path, "clang", "share",
+                                                     "clang", "run-clang-tidy.py")
+            self._clang_format_diff = mozpath.join(clang_tools_path, "clang", "share",
+                                                   "clang", "clang-format-diff.py")
+
+            # Ensure that clang-tidy is present
+            rc = not os.path.exists(self._clang_tidy_path)
+        else:
+            rc = self._get_clang_tools(force=force_download, verbose=verbose)
+
+        if rc != 0:
+            self.log(logging.ERROR, 'ERROR: static-analysis', {}, 'clang-tidy unable to locate package.')
+            return TOOLS_FAILED_DOWNLOAD
+
+        self._clang_tidy_base_path = mozpath.join(self.topsrcdir, "tools", "clang-tidy")
+
+        # For each checker run it
+        f = open(mozpath.join(self._clang_tidy_base_path, "config.yaml"))
+        import yaml
+        config = yaml.load(f)
+        platform, _ = self.platform
+
+        if platform not in config['platforms']:
+            self.log(logging.ERROR, 'static-analysis', {},"RUNNING: clang-tidy autotest for platform {} not supported.".format(platform))
+            return TOOLS_UNSUPORTED_PLATFORM
+
+        self.log(logging.INFO, 'static-analysis', {},"RUNNING: clang-tidy autotest for platform {}.".format(platform))
+        for item in config['clang_checkers']:
+            # Do not test mozilla specific checks nor the default '-*'
+            if not (item['publish'] and (
+                    'restricted-platforms' in item
+                    and platform not in item['restricted-platforms']
+                    or 'restricted-platforms' not in item) and item['name'] not in [
+                        'mozilla-*', '-*'
+                    ] and (checker_names == [] or item['name'] in checker_names)):
+                continue
+
+            check = item['name']
+            test_file_path = mozpath.join(self._clang_tidy_base_path, "test", check)
+            test_file_path_cpp = test_file_path + '.cpp'
+            test_file_path_json = test_file_path + '.json'
+
+            self.log(logging.INFO, 'static-analysis', {},"RUNNING: clang-tidy checker {}.".format(check))
+
+            # Verify is test file exists for checker
+            if not os.path.exists(test_file_path_cpp):
+                self.log(logging.ERROR, 'static-analysis', {}, "ERROR: clang-tidy checker {} doesn't have a test file.".format(check))
+                return TOOLS_CHECKER_NO_TEST_FILE
+
+            cmd = [self._clang_tidy_path, '-checks=-*, ' + check, test_file_path_cpp]
+
+            clang_output = subprocess.check_output(
+                cmd, stderr=subprocess.STDOUT).decode('utf-8')
+
+            issues = self._parse_issues(clang_output)
+
+            # Verify to see if we got any issues, if not raise exception
+            if not issues:
+                self.log(
+                    logging.ERROR, 'static-analysis', {},
+                    "ERROR: clang-tidy checker {0} did not find any issues in it\'s associated test suite.".
+                    format(check))
+                return CHECKER_RETURNED_NO_ISSUES
+
+            if dump_results:
+                self._build_autotest_result(test_file_path_json, issues)
+            else:
+                if not os.path.exists(test_file_path_json):
+                    # Result file for test not found maybe regenerate it?
+                    self.log(
+                        logging.ERROR, 'static-analysis', {},
+                        "ERROR: clang-tidy result file not found for checker {0}".format(
+                            check))
+                    return TOOLS_CHECKER_RESULT_FILE_NOT_FOUND
+                # Read the pre-determined issues
+                baseline_issues = self._get_autotest_stored_issues(test_file_path_json)
+
+                # Compare the two lists
+                if issues != baseline_issues:
+                    print("Clang output: {}".format(clang_output))
+                    self.log(
+                        logging.ERROR, 'static-analysis', {},
+                        "ERROR: clang-tidy auto-test failed for checker {0} Expected: {1} Got: {2}".
+                        format(check, baseline_issues, issues))
+                    return TOOLS_CHECKER_DIFF_FAILED
+        self.log(logging.INFO, 'static-analysis', {},"SUCCESS: clang-tidy all tests passed.")
+        return TOOLS_SUCCESS
+
+
     @StaticAnalysisSubCommand('static-analysis', 'install',
                               'Install the static analysis helper tool')
     @CommandArgument('source', nargs='?', type=str,
                      help='Where to fetch a local archive containing the static-analysis and format helper tool.'
                           'It will be installed in ~/.mozbuild/clang-tools/.'
                           'Can be omitted, in which case the latest clang-tools '
                           ' helper for the platform would be automatically '
                           'detected and installed.')
@@ -1761,16 +1891,51 @@ class StaticAnalysis(MachCommandBase):
             return rc
 
         if path is None:
             return self._run_clang_format_diff(self._clang_format_diff,
                                                self._clang_format_path, show)
         else:
             return self._run_clang_format_path(self._clang_format_path, show, path)
 
+    def _build_autotest_result(self, file, issues):
+        with open(file, 'w') as f:
+            json.dump(issues, f, indent=4, sort_keys=True)
+
+    def _get_autotest_stored_issues(self, file):
+        with open(file) as f:
+            return json.load(f)
+
+    def _parse_issues(self, clang_output):
+        '''
+        Parse clang-tidy output into structured issues
+        '''
+
+        # Limit clang output parsing to 'Enabled checks:'
+        end = re.search(r'^Enabled checks:\n', clang_output, re.MULTILINE)
+        if end is not None:
+            clang_output = clang_output[:end.start()-1]
+
+        # Sort headers by positions
+        regex_header = re.compile(
+            r'(.+):(\d+):(\d+): (warning|error): ([^\[\]\n]+)(?: \[([\.\w-]+)\])?$', re.MULTILINE)
+
+        something = regex_header.finditer(clang_output)
+        headers = sorted(
+            regex_header.finditer(clang_output),
+            key=lambda h: h.start()
+        )
+
+        issues = []
+        for _, header in enumerate(headers):
+            header_group = header.groups()
+            element = [header_group[3], header_group[4], header_group[5]]
+            issues.append(element)
+        return json.dumps(issues)
+
     def _get_checks(self):
         checks = '-*'
         import yaml
         with open(mozpath.join(self.topsrcdir, "tools", "clang-tidy", "config.yaml")) as f:
             try:
                 config = yaml.load(f)
                 for item in config['clang_checkers']:
                     if item['publish']:
@@ -1839,42 +2004,43 @@ class StaticAnalysis(MachCommandBase):
 
         # Then build the rest of the build dependencies by running the full
         # export target, because we can't do anything better.
         return builder._run_make(directory=self.topobjdir, target='export',
                                  line_handler=None, silent=not verbose,
                                  num_jobs=jobs)
 
     def _conv_to_abspath(self, paths):
-            # Converts all the paths to absolute pathnames
+        # Converts all the paths to absolute pathnames
         tmp_path = []
         for f in paths:
             tmp_path.append(os.path.abspath(f))
         return tmp_path
 
     def _get_clang_tools(self, force=False, skip_cache=False,
                          source=None, download_if_needed=True,
                          verbose=False):
         rc, config, _ = self._get_config_environment()
 
         if rc != 0:
             return rc
 
-        clang_tools_path = mozpath.join(self._mach_context.state_dir,
-                                        "clang-tools")
+        clang_tools_path = mozpath.join(self._mach_context.state_dir, "clang-tools")
         self._clang_tidy_path = mozpath.join(clang_tools_path, "clang", "bin",
                                              "clang-tidy" + config.substs.get('BIN_SUFFIX', ''))
-        self._clang_format_path = mozpath.join(clang_tools_path, "clang", "bin",
-                                               "clang-format" + config.substs.get('BIN_SUFFIX', ''))
-        self._clang_apply_replacements = mozpath.join(clang_tools_path, "clang", "bin",
-                                                      "clang-apply-replacements" + config.substs.get('BIN_SUFFIX', ''))
-        self._run_clang_tidy_path = mozpath.join(clang_tools_path, "clang", "share",
-                                                 "clang", "run-clang-tidy.py")
-        self._clang_format_diff = mozpath.join(clang_tools_path, "clang", "share",
-                                               "clang", "clang-format-diff.py")
+        self._clang_format_path = mozpath.join(
+            clang_tools_path, "clang", "bin",
+            "clang-format" + config.substs.get('BIN_SUFFIX', ''))
+        self._clang_apply_replacements = mozpath.join(
+            clang_tools_path, "clang", "bin",
+            "clang-apply-replacements" + config.substs.get('BIN_SUFFIX', ''))
+        self._run_clang_tidy_path = mozpath.join(clang_tools_path, "clang", "share", "clang",
+                                                 "run-clang-tidy.py")
+        self._clang_format_diff = mozpath.join(clang_tools_path, "clang", "share", "clang",
+                                               "clang-format-diff.py")
 
         if os.path.exists(self._clang_tidy_path) and \
            os.path.exists(self._clang_format_path) and \
            os.path.exists(self._clang_apply_replacements) and \
            os.path.exists(self._run_clang_tidy_path) and \
            not force:
             return 0
         else:
new file mode 100644
--- /dev/null
+++ b/taskcluster/ci/static-analysis-autotest/kind.yml
@@ -0,0 +1,47 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+loader: taskgraph.loader.transform:loader
+
+kind-dependencies:
+    - toolchain
+
+transforms:
+    - taskgraph.transforms.build_attrs:transforms
+    - taskgraph.transforms.use_toolchains:transforms
+    - taskgraph.transforms.job:transforms
+    - taskgraph.transforms.task:transforms
+
+job-defaults:
+    index:
+        product: firefox
+    treeherder:
+        symbol: Sa
+        kind: build
+        tier: 1
+
+jobs:
+    linux64-st-autotest/debug:
+        description: "Linux64 Debug Static Analysis Autotest"
+        index:
+            job-name: linux64-st-autotest-debug
+        treeherder:
+            platform: linux64/debug
+        worker-type: aws-provisioner-v1/gecko-t-linux-large
+        worker:
+            max-run-time: 3600
+        run:
+            using: mozharness
+            actions: [static-analysis-autotest]
+            config:
+                - builds/releng_base_firefox.py
+                - builds/releng_sub_linux_configs/64_stat_and_debug.py
+            script: "mozharness/scripts/fx_desktop_build.py"
+            tooltool-downloads: public
+            keep-artifacts: false
+        toolchains:
+            - linux64-clang
+            - linux64-clang-tidy
+            - linux64-rust
+            - linux64-sccache
--- a/taskcluster/docs/kinds.rst
+++ b/taskcluster/docs/kinds.rst
@@ -85,16 +85,22 @@ Searchfox builds generate C++ index data
 static-analysis
 ---------------
 
 Static analysis builds use the compiler to perform some detailed analysis of
 the source code while building.  The useful output from these tasks are their
 build logs, and while they produce a binary, they do not upload it as an
 artifact.
 
+static-analysis-autotest
+---------------
+
+Static analysis autotest utility in order to be sure that there is no regression
+when upgrading utilities that impact static-analysis.
+
 toolchain
 ---------
 
 Toolchain builds create the compiler toolchains used to build Firefox.  These
 will eventually be dependencies of the builds themselves, but for the moment
 are run manually via try pushes and the results uploaded to tooltool.
 
 spidermonkey
--- a/testing/mozharness/mozharness/mozilla/building/buildbase.py
+++ b/testing/mozharness/mozharness/mozilla/building/buildbase.py
@@ -1263,16 +1263,21 @@ or run without that action (ie: --no-{ac
         """builds application."""
 
         # This will error on non-0 exit code.
         self._run_mach_command_in_build_env(['build', '-v'])
 
         self.generate_build_props(console_output=True, halt_on_failure=True)
         self._generate_build_stats()
 
+    def static_analysis_autotest(self):
+        """Run mach static-analysis autotest, in order to make sure we dont regress"""
+        self.preflight_build()
+        self._run_mach_command_in_build_env(['static-analysis', 'autotest', '--intree-tool'])
+
     def _run_mach_command_in_build_env(self, args):
         """Run a mach command in a build context."""
         env = self.query_build_env()
         env.update(self.query_mach_build_env())
 
         # XXX Bug 1037883 - mozconfigs can not find buildprops.json when builds
         # are through mozharness. This is not pretty but it is a stopgap
         # until an alternative solution is made or all builds that touch
--- a/testing/mozharness/scripts/fx_desktop_build.py
+++ b/testing/mozharness/scripts/fx_desktop_build.py
@@ -31,16 +31,17 @@ from mozharness.mozilla.testing.try_tool
 class FxDesktopBuild(BuildScript, TryToolsMixin, object):
     def __init__(self):
         buildscript_kwargs = {
             'config_options': BUILD_BASE_CONFIG_OPTIONS + copy.deepcopy(try_config_options),
             'all_actions': [
                 'get-secrets',
                 'clobber',
                 'build',
+                'static-analysis-autotest',
                 'check-test',
                 'valgrind-test',
                 'multi-l10n',
                 'package-source',
                 'update',
                 'ensure-upload-path',
             ],
             'require_config_file': True,
--- a/tools/clang-tidy/config.yaml
+++ b/tools/clang-tidy/config.yaml
@@ -1,90 +1,108 @@
 ---
 target: obj-x86_64-pc-linux-gnu
 # It is used by 'mach static-analysis' and 'mozreview static-analysis bot'
 # in order to have consistency across the used checkers.
 # All the clang checks used by the static-analysis tools.
+platforms:
+  - macosx64
+  - linux64
+  - win64
+  - win32
 clang_checkers:
- - name: -*
-   publish: !!bool no
- - name: misc-forward-declaration-namespace
-   # Name with clang tidy 6.0. We are currently using 5.0
-   # - name: bugprone-forward-declaration-namespace
-   publish: !!bool yes
- - name: clang-analyzer-deadcode.DeadStores
-   publish: !!bool yes
- - name: clang-analyzer-security.FloatLoopCounter
-   publish: !!bool yes
- - name: clang-analyzer-security.insecureAPI.UncheckedReturn
-   publish: !!bool yes
- - name: clang-analyzer-security.insecureAPI.getpw
-   publish: !!bool yes
- - name: clang-analyzer-security.insecureAPI.mkstemp
-   publish: !!bool yes
- - name: clang-analyzer-security.insecureAPI.mktemp
-   publish: !!bool yes
- - name: clang-analyzer-security.insecureAPI.rand
-   publish: !!bool yes
- - name: clang-analyzer-security.insecureAPI.strcpy
-   publish: !!bool no
- - name: clang-analyzer-security.insecureAPI.vfork
-   publish: !!bool yes
- - name: misc-argument-comment
-   publish: !!bool yes
- - name: misc-assert-side-effect
-   publish: !!bool yes
- - name: misc-suspicious-missing-comma
-   publish: !!bool yes
- - name: misc-suspicious-semicolon
-   publish: !!bool yes
- - name: misc-unused-using-decls
-   publish: !!bool yes
- - name: modernize-avoid-bind
-   publish: !!bool yes
- - name: modernize-loop-convert
-   publish: !!bool yes
- - name: modernize-raw-string-literal
-   publish: !!bool yes
- - name: modernize-redundant-void-arg
-   publish: !!bool no
- - name: modernize-shrink-to-fit
-   publish: !!bool yes
- - name: modernize-use-equals-default
-   publish: !!bool yes
- - name: modernize-use-equals-delete
-   publish: !!bool yes
- - name: modernize-use-nullptr
-   publish: !!bool yes
- - name: modernize-use-override
-   # Too noisy because of the way how we implement NS_IMETHOD. See Bug 1420366.
-   publish: !!bool no
- - name: mozilla-*
-   publish: !!bool yes
- - name: performance-*
-   publish: !!bool yes
- - name: readability-container-size-empty
-   publish: !!bool yes
- - name: readability-else-after-return
-   publish: !!bool yes
- - name: readability-misleading-indentation
-   publish: !!bool yes
- - name: readability-redundant-control-flow
-   publish: !!bool yes
- - name: readability-redundant-smartptr-get
-   publish: !!bool no
- - name: readability-redundant-string-cstr
-   publish: !!bool yes
- - name: readability-redundant-string-init
-   publish: !!bool yes
- - name: readability-uniqueptr-delete-release
-   publish: !!bool yes
- - name: modernize-use-auto
-   # Controversial, see bug 1371052.
-   publish: !!bool no
- - name: modernize-use-bool-literals
-   publish: !!bool yes
+  - name: -*
+    publish: !!bool no
+  - name: misc-forward-declaration-namespace
+    # Name with clang tidy 6.0. We are currently using 5.0
+    # - name: bugprone-forward-declaration-namespace
+    publish: !!bool yes
+  - name: clang-analyzer-deadcode.DeadStores
+    publish: !!bool yes
+  - name: clang-analyzer-security.FloatLoopCounter
+    publish: !!bool yes
+  - name: clang-analyzer-security.insecureAPI.UncheckedReturn
+    publish: !!bool yes
+  - name: clang-analyzer-security.insecureAPI.getpw
+    publish: !!bool yes
+  - name: clang-analyzer-security.insecureAPI.mkstemp
+    publish: !!bool yes
+  - name: clang-analyzer-security.insecureAPI.mktemp
+    publish: !!bool yes
+  - name: clang-analyzer-security.insecureAPI.rand
+    publish: !!bool no
+  - name: clang-analyzer-security.insecureAPI.strcpy
+    publish: !!bool no
+  - name: clang-analyzer-security.insecureAPI.vfork
+    publish: !!bool yes
+  - name: misc-argument-comment
+    publish: !!bool yes
+  - name: misc-assert-side-effect
+    publish: !!bool yes
+  - name: misc-suspicious-missing-comma
+    publish: !!bool yes
+  - name: misc-suspicious-semicolon
+    publish: !!bool yes
+  - name: misc-unused-using-decls
+    publish: !!bool yes
+  - name: modernize-avoid-bind
+    publish: !!bool yes
+    restricted-platforms:
+      - win32
+      - win64
+  - name: modernize-loop-convert
+    publish: !!bool yes
+  - name: modernize-raw-string-literal
+    publish: !!bool yes
+  - name: modernize-redundant-void-arg
+    publish: !!bool no
+  - name: modernize-shrink-to-fit
+    publish: !!bool yes
+  - name: modernize-use-equals-default
+    publish: !!bool yes
+  - name: modernize-use-equals-delete
+    publish: !!bool yes
+  - name: modernize-use-nullptr
+    publish: !!bool yes
+  - name: modernize-use-override
+    # Too noisy because of the way how we implement NS_IMETHOD. See Bug 1420366.
+    publish: !!bool no
+  - name: mozilla-*
+    publish: !!bool yes
+  - name: performance-for-range-copy
+    publish: !!bool yes
+  - name: performance-inefficient-string-concatenation
+    publish: !!bool yes
+  - name: performance-inefficient-vector-operation
+    publish: !!bool yes
+  - name: performance-type-promotion-in-math-fn
+    publish: !!bool yes
+  - name: performance-unnecessary-copy-initialization
+    publish: !!bool yes
+  - name: performance-unnecessary-value-param
+    publish: !!bool yes
+  - name: readability-container-size-empty
+    publish: !!bool yes
+  - name: readability-else-after-return
+    publish: !!bool yes
+  - name: readability-misleading-indentation
+    publish: !!bool yes
+  - name: readability-redundant-control-flow
+    publish: !!bool yes
+  - name: readability-redundant-smartptr-get
+    publish: !!bool no
+  - name: readability-redundant-string-cstr
+    publish: !!bool yes
+  - name: readability-redundant-string-init
+    publish: !!bool yes
+  - name: readability-uniqueptr-delete-release
+    publish: !!bool yes
+  - name: modernize-use-auto
+    # Controversial, see bug 1371052.
+    publish: !!bool no
+  - name: modernize-use-bool-literals
+    publish: !!bool yes
 # Only available from clang tidy 6.0. We are currently using 5.0
 # - name: readability-static-accessed-through-instance
 #   publish: !!bool yes
 
 # Third party files from mozilla-central
 third_party: tools/rewriting/ThirdPartyPaths.txt
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-deadcode.DeadStores.cpp
@@ -0,0 +1,7 @@
+
+// clang-analyzer-deadcode.DeadStores
+void test() {
+  int x;
+  x = 1; // warn
+}
+
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-deadcode.DeadStores.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"Value stored to 'x' is never read\", \"clang-analyzer-deadcode.DeadStores\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.FloatLoopCounter.cpp
@@ -0,0 +1,3 @@
+void test() {
+  for (float x = 0.1f; x <= 1.0f; x += 0.1f) {}
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.FloatLoopCounter.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"Variable 'x' with floating point type 'float' should not be used as a loop counter\", \"clang-analyzer-security.FloatLoopCounter\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.UncheckedReturn.cpp
@@ -0,0 +1,5 @@
+#include "structures.h"
+
+void test() {
+  setuid(1);
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.UncheckedReturn.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"The return value from the call to 'setuid' is not checked.  If an error occurs in 'setuid', the following code may execute with unexpected privileges\", \"clang-analyzer-security.insecureAPI.UncheckedReturn\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.getpw.cpp
@@ -0,0 +1,6 @@
+#include "structures.h"
+
+void test() {
+  char buff[1024];
+  getpw(2, buff);
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.getpw.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"The getpw() function is dangerous as it may overflow the provided buffer. It is obsoleted by getpwuid()\", \"clang-analyzer-security.insecureAPI.getpw\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.gets.cpp
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void test() {
+  char buff[1024];
+  gets(buff);
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.gets.json
@@ -0,0 +1,1 @@
+"[[\"error\", \"use of undeclared identifier 'gets'\", \"clang-diagnostic-error\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.mkstemp.cpp
@@ -0,0 +1,5 @@
+#include "structures.h"
+
+void test() {
+  mkstemp("XX");
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.mkstemp.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"Call to 'mkstemp' should have at least 6 'X's in the format string to be secure (2 'X's seen)\", \"clang-analyzer-security.insecureAPI.mkstemp\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.mktemp.cpp
@@ -0,0 +1,5 @@
+#include "structures.h"
+
+void test() {
+  char *x = mktemp("/tmp/zxcv");
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.mktemp.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"Call to function 'mktemp' is insecure as it always creates or uses insecure temporary file.  Use 'mkstemp' instead\", \"clang-analyzer-security.insecureAPI.mktemp\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.rand.cpp
@@ -0,0 +1,4 @@
+#include <stdlib.h>
+void test() {
+  random();
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.rand.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"The 'random' function produces a sequence of values that an adversary may be able to predict.  Use 'arc4random' instead\", \"clang-analyzer-security.insecureAPI.rand\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.strcpy.cpp
@@ -0,0 +1,7 @@
+#include <string.h>
+void test() {
+  char x[4];
+  char *y = "abcd";
+
+  strcpy(x, y);
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.strcpy.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119\", \"clang-analyzer-security.insecureAPI.strcpy\"], [\"note\", \"Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119\", null]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.vfork.cpp
@@ -0,0 +1,5 @@
+#include "structures.h"
+
+void test() {
+  vfork();
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/clang-analyzer-security.insecureAPI.vfork.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"Call to function 'vfork' is insecure as it can lead to denial of service situations in the parent process. Replace calls to vfork with calls to the safer 'posix_spawn' function\", \"clang-analyzer-security.insecureAPI.vfork\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-argument-comment.cpp
@@ -0,0 +1,6 @@
+
+// misc-argument-comment
+void f(int x, int y);
+void g() {
+  f(/*y=*/0, /*z=*/0);
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-argument-comment.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"argument name 'y' in comment does not match parameter name 'x'\", \"misc-argument-comment\"], [\"warning\", \"argument name 'z' in comment does not match parameter name 'y'\", \"misc-argument-comment\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-assert-side-effect.cpp
@@ -0,0 +1,9 @@
+
+#include "structures.h"
+
+// misc-assert-side-effect
+void misc_assert_side_effect() {
+  int X = 0;
+  assert(X == 1);
+  assert(X = 1);
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-assert-side-effect.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"found assert() with side effect\", \"misc-assert-side-effect\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-forward-declaration-namespace.cpp
@@ -0,0 +1,3 @@
+namespace na { struct A; }
+namespace nb { struct A {}; }
+nb::A a;
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-forward-declaration-namespace.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"no definition found for 'A', but a definition with the same name 'A' found in another namespace 'nb'\", \"misc-forward-declaration-namespace\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-suspicious-missing-comma.cpp
@@ -0,0 +1,9 @@
+
+// misc-suspicious-missing-comma
+const char* software[] = {
+  "Firefox",
+  "Rust"   // There is a missing comma here.
+  "Thunderbird",
+  "kinto"
+};
+
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-suspicious-missing-comma.json
@@ -0,0 +1,1 @@
+"[]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-suspicious-semicolon.cpp
@@ -0,0 +1,8 @@
+
+// misc-suspicious-semicolon
+void nop();
+void fail1()
+{
+    int x = 0;
+    if(x > 5); nop();
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-suspicious-semicolon.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"potentially unintended semicolon\", \"misc-suspicious-semicolon\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-unused-using-decls.cpp
@@ -0,0 +1,4 @@
+
+// misc-unused-using-decls
+namespace n { class C; }
+using n::C;
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/misc-unused-using-decls.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"using decl 'C' is unused\", \"misc-unused-using-decls\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-avoid-bind.cpp
@@ -0,0 +1,6 @@
+#include "structures.h"
+
+int add(int x, int y) { return x + y; }
+void f_bind() {
+    auto clj = std::bind(add, 2, 2);
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-avoid-bind.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"prefer a lambda to std::bind\", \"modernize-avoid-bind\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-loop-convert.cpp
@@ -0,0 +1,7 @@
+int arr[6] = {1, 2, 3, 4, 5, 6};
+
+void bar(void) {
+  for (int i = 0; i < 6; ++i) {
+    (void)arr[i];
+  }
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-loop-convert.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"use range-based for loop instead\", \"modernize-loop-convert\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-raw-string-literal.cpp
@@ -0,0 +1,1 @@
+char const *const ManyQuotes("quotes:\'\'\'\'");
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-raw-string-literal.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"escaped string literal can be written as a raw string literal\", \"modernize-raw-string-literal\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-redundant-void-arg.cpp
@@ -0,0 +1,5 @@
+// modernize-redundant-void-arg
+
+int foo(void) {
+    return 0;
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-redundant-void-arg.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"redundant void argument list in function definition\", \"modernize-redundant-void-arg\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-shrink-to-fit.cpp
@@ -0,0 +1,10 @@
+#include "structures.h"
+
+void f() {
+  std::vector<int> v;
+
+  std::vector<int>(v).swap(v);
+
+  std::vector<int> &vref = v;
+  std::vector<int>(vref).swap(vref);
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-shrink-to-fit.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"the shrink_to_fit method should be used to reduce the capacity of a shrinkable container\", \"modernize-shrink-to-fit\"], [\"warning\", \"the shrink_to_fit method should be used to reduce the capacity of a shrinkable container\", \"modernize-shrink-to-fit\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-auto.cpp
@@ -0,0 +1,11 @@
+#include <vector>
+
+void func() {
+  int val = 42;
+  std::vector<int> my_container;
+  for (std::vector<int>::iterator I = my_container.begin(),
+                                  E = my_container.end();
+       I != E;
+       ++I) {
+  }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-auto.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"use auto when declaring iterators\", \"modernize-use-auto\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-bool-literals.cpp
@@ -0,0 +1,5 @@
+void foo() {
+  bool p = 1;
+  bool f = static_cast<bool>(1);
+  bool x = p ? 1 : 0;
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-bool-literals.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"converting integer literal to bool, use bool literal instead\", \"modernize-use-bool-literals\"], [\"warning\", \"converting integer literal to bool, use bool literal instead\", \"modernize-use-bool-literals\"], [\"warning\", \"converting integer literal to bool, use bool literal instead\", \"modernize-use-bool-literals\"], [\"warning\", \"converting integer literal to bool, use bool literal instead\", \"modernize-use-bool-literals\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-equals-default.cpp
@@ -0,0 +1,6 @@
+
+class IL {
+public:
+  IL() {}
+  ~IL() {}
+};
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-equals-default.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"use '= default' to define a trivial default constructor\", \"modernize-use-equals-default\"], [\"warning\", \"use '= default' to define a trivial destructor\", \"modernize-use-equals-default\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-equals-delete.cpp
@@ -0,0 +1,7 @@
+struct PositivePrivate {
+private:
+  PositivePrivate();
+  PositivePrivate(const PositivePrivate &);
+  PositivePrivate &operator=(PositivePrivate &&);
+  ~PositivePrivate();
+};
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-equals-delete.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"use '= delete' to prohibit calling of a special member function\", \"modernize-use-equals-delete\"], [\"warning\", \"use '= delete' to prohibit calling of a special member function\", \"modernize-use-equals-delete\"], [\"warning\", \"use '= delete' to prohibit calling of a special member function\", \"modernize-use-equals-delete\"], [\"warning\", \"use '= delete' to prohibit calling of a special member function\", \"modernize-use-equals-delete\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-nullptr.cpp
@@ -0,0 +1,5 @@
+#define NULL 0
+void f(void) {
+  char *str = NULL; // ok
+  (void)str;
+}
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-nullptr.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"use nullptr\", \"modernize-use-nullptr\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-override.cpp
@@ -0,0 +1,8 @@
+class Base {
+public:
+  virtual void foo() = 0;
+};
+
+class Deriv : public Base {
+  void foo();
+};
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/modernize-use-override.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"annotate this function with 'override' or (rarely) 'final'\", \"modernize-use-override\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-faster-string-find.cpp
@@ -0,0 +1,6 @@
+#include <string>
+
+void foo() {
+  std::string str;
+  str.find("A");
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-faster-string-find.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"'find' called with a string literal consisting of a single character; consider using the more effective overload accepting a character\", \"performance-faster-string-find\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-for-range-copy.cpp
@@ -0,0 +1,30 @@
+template <typename T>
+struct Iterator {
+  void operator++() {}
+  const T& operator*() {
+    static T* TT = new T();
+    return *TT;
+  }
+  bool operator!=(const Iterator &) { return false; }
+  typedef const T& const_reference;
+};
+template <typename T>
+struct View {
+  T begin() { return T(); }
+  T begin() const { return T(); }
+  T end() { return T(); }
+  T end() const { return T(); }
+  typedef typename T::const_reference const_reference;
+};
+
+struct S {
+  S();
+  S(const S &);
+  ~S();
+  S &operator=(const S &);
+};
+
+void negativeConstReference() {
+  for (const S S1 : View<Iterator<S>>()) {
+  }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-for-range-copy.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"the loop variable's type is not a reference type; this creates a copy in each iteration; consider making this a reference\", \"performance-for-range-copy\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-inefficient-string-concatenation.cpp
@@ -0,0 +1,13 @@
+#include "structures.h"
+
+extern void fstring(std::string);
+
+void foo() {
+  std::string mystr1, mystr2;
+  auto myautostr1 = mystr1;
+  auto myautostr2 = mystr2;
+
+  for (int i = 0; i < 10; ++i) {
+    fstring(mystr1 + mystr2 + mystr1);
+  }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-inefficient-string-concatenation.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"string concatenation results in allocation of unnecessary temporary strings; consider using 'operator+=' or 'string::append()' instead\", \"performance-inefficient-string-concatenation\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-inefficient-vector-operation.cpp
@@ -0,0 +1,10 @@
+#include "structures.h"
+
+void foo()
+{
+  std::vector<int> v;
+  int n = 100;
+  for (int i = 0; i < n; ++i) {
+    v.push_back(n);
+  }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-inefficient-vector-operation.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"'push_back' is called inside a loop; consider pre-allocating the vector capacity before the loop\", \"performance-inefficient-vector-operation\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-type-promotion-in-math-fn.cpp
@@ -0,0 +1,7 @@
+double acos(double);
+
+void check_all_fns()
+{
+  float a;
+  acos(a);
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-type-promotion-in-math-fn.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"call to 'acos' promotes float to double\", \"performance-type-promotion-in-math-fn\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-unnecessary-copy-initialization.cpp
@@ -0,0 +1,7 @@
+#include "structures.h"
+
+extern const std::string& constReference();
+
+void foo() {
+  const std::string UnnecessaryCopy = constReference();
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-unnecessary-copy-initialization.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"the const qualified variable 'UnnecessaryCopy' is copy-constructed from a const reference; consider making it a const reference\", \"performance-unnecessary-copy-initialization\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-unnecessary-value-param.cpp
@@ -0,0 +1,4 @@
+#include "structures.h"
+
+void f(const std::string Value) {
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/performance-unnecessary-value-param.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"the const qualified parameter 'Value' is copied for each invocation; consider making it a reference\", \"performance-unnecessary-value-param\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-container-size-empty.cpp
@@ -0,0 +1,7 @@
+#include "structures.h"
+
+void foo() {
+  std::string a;
+  if (a.size())
+    return;
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-container-size-empty.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"the 'empty' method should be used to check for emptiness instead of 'size'\", \"readability-container-size-empty\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-else-after-return.cpp
@@ -0,0 +1,10 @@
+void f() {
+
+}
+
+void foo() {
+  if (true)
+    return;
+  else
+    f();
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-else-after-return.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"do not use 'else' after 'return'\", \"readability-else-after-return\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-misleading-indentation.cpp
@@ -0,0 +1,11 @@
+void f()
+{
+}
+
+void foo() {
+  if (1)
+    if (0)
+      f();
+  else
+    f();
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-misleading-indentation.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"different indentation for 'if' and corresponding 'else'\", \"readability-misleading-indentation\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-redundant-control-flow.cpp
@@ -0,0 +1,5 @@
+extern void g();
+void f() {
+  g();
+  return;
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-redundant-control-flow.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"redundant return statement at the end of a function with a void return type\", \"readability-redundant-control-flow\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-redundant-smartptr-get.cpp
@@ -0,0 +1,11 @@
+#include <memory>
+
+struct A {
+  void f() {}
+};
+
+void foo() {
+  std::unique_ptr<A> ptr = std::make_unique<A>();
+  ptr.get()->f();
+}
+
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-redundant-smartptr-get.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"redundant get() call on smart pointer\", \"readability-redundant-smartptr-get\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-redundant-string-cstr.cpp
@@ -0,0 +1,7 @@
+#include "structures.h"
+
+void foo() {
+  std::string a = "Mozilla";
+  std::string tmp;
+  tmp.assign(a.c_str());
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-redundant-string-cstr.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"redundant call to 'c_str'\", \"readability-redundant-string-cstr\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-redundant-string-init.cpp
@@ -0,0 +1,5 @@
+#include "structures.h"
+
+int foo() {
+  std::string a = "";
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-redundant-string-init.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"redundant string initialization\", \"readability-redundant-string-init\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-uniqueptr-delete-release.cpp
@@ -0,0 +1,6 @@
+#include "structures.h"
+
+int foo() {
+  std::unique_ptr<int> P;
+  delete P.release();
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/readability-uniqueptr-delete-release.json
@@ -0,0 +1,1 @@
+"[[\"warning\", \"prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> objects\", \"readability-uniqueptr-delete-release\"]]"
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/tools/clang-tidy/test/structures.h
@@ -0,0 +1,88 @@
+// Proxy file in order to define generic data types, to void binding with system headers
+
+namespace std {
+
+typedef unsigned long size_t;
+
+template <class T>
+class vector {
+ public:
+  typedef T* iterator;
+  typedef const T* const_iterator;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef size_t size_type;
+
+  explicit vector();
+  explicit vector(size_type n);
+
+  void swap(vector &other);
+  void push_back(const T& val);
+
+  template <class... Args> void emplace_back(Args &&... args);
+
+  void reserve(size_t n);
+  void resize(size_t n);
+
+  size_t size();
+  const_reference operator[] (size_type) const;
+  reference operator[] (size_type);
+
+  const_iterator begin() const;
+  const_iterator end() const;
+};
+
+template <typename T>
+class basic_string {
+public:
+  typedef basic_string<T> _Type;
+  basic_string() {}
+   basic_string(const T *p);
+  ~basic_string() {}
+  size_t size() const;
+  bool empty() const;
+  const T *c_str() const;
+  _Type& assign(const T *s);
+  basic_string<T> *operator+=(const basic_string<T> &) {}
+  friend basic_string<T> operator+(const basic_string<T> &, const basic_string<T> &) {}
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+
+template <typename T>
+struct default_delete {};
+
+template <typename T, typename D = default_delete<T>>
+class unique_ptr {
+ public:
+  unique_ptr();
+  ~unique_ptr();
+  explicit unique_ptr(T*);
+  template <typename U, typename E>
+  unique_ptr(unique_ptr<U, E>&&);
+  T* release();
+};
+
+template <class Fp, class... Arguments>
+class bind_rt {};
+
+template <class Fp, class... Arguments>
+bind_rt<Fp, Arguments...> bind(Fp &&, Arguments &&...);
+}
+
+typedef unsigned int uid_t;
+typedef unsigned int pid_t;
+
+int getpw(uid_t uid, char *buf);
+int setuid(uid_t uid);
+
+int mkstemp(char *tmpl);
+char *mktemp(char *tmpl);
+
+pid_t vfork(void);
+
+int abort() { return 0; }
+
+#define assert(x)                                                              \
+  if (!(x))                                                                    \
+  (void)abort()