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

--HG--
extra : rebase_source : e6860d1adcc06bb1e4383cb76be02089a0ef61f9
This commit is contained in:
Andi-Bogdan Postelnicu 2018-05-03 20:06:16 +03:00
parent 41a9c35cf2
commit 7ff371efa8
91 changed files with 764 additions and 89 deletions

View File

@ -1704,6 +1704,136 @@ class StaticAnalysis(MachCommandBase):
'{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,
@ -1765,6 +1895,41 @@ class StaticAnalysis(MachCommandBase):
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
@ -1843,7 +2008,7 @@ class StaticAnalysis(MachCommandBase):
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))
@ -1857,18 +2022,19 @@ class StaticAnalysis(MachCommandBase):
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 \

View File

@ -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

View File

@ -90,6 +90,12 @@ 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
---------

View File

@ -1268,6 +1268,11 @@ or run without that action (ie: --no-{action})"
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()

View File

@ -36,6 +36,7 @@ class FxDesktopBuild(BuildScript, TryToolsMixin, object):
'get-secrets',
'clobber',
'build',
'static-analysis-autotest',
'check-test',
'valgrind-test',
'multi-l10n',

View File

@ -3,85 +3,103 @@ 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

View File

@ -0,0 +1,7 @@
// clang-analyzer-deadcode.DeadStores
void test() {
int x;
x = 1; // warn
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"Value stored to 'x' is never read\", \"clang-analyzer-deadcode.DeadStores\"]]"

View File

@ -0,0 +1,3 @@
void test() {
for (float x = 0.1f; x <= 1.0f; x += 0.1f) {}
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"Variable 'x' with floating point type 'float' should not be used as a loop counter\", \"clang-analyzer-security.FloatLoopCounter\"]]"

View File

@ -0,0 +1,5 @@
#include "structures.h"
void test() {
setuid(1);
}

View File

@ -0,0 +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\"]]"

View File

@ -0,0 +1,6 @@
#include "structures.h"
void test() {
char buff[1024];
getpw(2, buff);
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"The getpw() function is dangerous as it may overflow the provided buffer. It is obsoleted by getpwuid()\", \"clang-analyzer-security.insecureAPI.getpw\"]]"

View File

@ -0,0 +1,6 @@
#include <stdio.h>
void test() {
char buff[1024];
gets(buff);
}

View File

@ -0,0 +1 @@
"[[\"error\", \"use of undeclared identifier 'gets'\", \"clang-diagnostic-error\"]]"

View File

@ -0,0 +1,5 @@
#include "structures.h"
void test() {
mkstemp("XX");
}

View File

@ -0,0 +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\"]]"

View File

@ -0,0 +1,5 @@
#include "structures.h"
void test() {
char *x = mktemp("/tmp/zxcv");
}

View File

@ -0,0 +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\"]]"

View File

@ -0,0 +1,4 @@
#include <stdlib.h>
void test() {
random();
}

View File

@ -0,0 +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\"]]"

View File

@ -0,0 +1,7 @@
#include <string.h>
void test() {
char x[4];
char *y = "abcd";
strcpy(x, y);
}

View File

@ -0,0 +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]]"

View File

@ -0,0 +1,5 @@
#include "structures.h"
void test() {
vfork();
}

View File

@ -0,0 +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\"]]"

View File

@ -0,0 +1,6 @@
// misc-argument-comment
void f(int x, int y);
void g() {
f(/*y=*/0, /*z=*/0);
}

View File

@ -0,0 +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\"]]"

View File

@ -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);
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"found assert() with side effect\", \"misc-assert-side-effect\"]]"

View File

@ -0,0 +1,3 @@
namespace na { struct A; }
namespace nb { struct A {}; }
nb::A a;

View File

@ -0,0 +1 @@
"[[\"warning\", \"no definition found for 'A', but a definition with the same name 'A' found in another namespace 'nb'\", \"misc-forward-declaration-namespace\"]]"

View File

@ -0,0 +1,9 @@
// misc-suspicious-missing-comma
const char* software[] = {
"Firefox",
"Rust" // There is a missing comma here.
"Thunderbird",
"kinto"
};

View File

@ -0,0 +1 @@
"[]"

View File

@ -0,0 +1,8 @@
// misc-suspicious-semicolon
void nop();
void fail1()
{
int x = 0;
if(x > 5); nop();
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"potentially unintended semicolon\", \"misc-suspicious-semicolon\"]]"

View File

@ -0,0 +1,4 @@
// misc-unused-using-decls
namespace n { class C; }
using n::C;

View File

@ -0,0 +1 @@
"[[\"warning\", \"using decl 'C' is unused\", \"misc-unused-using-decls\"]]"

View File

@ -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);
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"prefer a lambda to std::bind\", \"modernize-avoid-bind\"]]"

View File

@ -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];
}
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"use range-based for loop instead\", \"modernize-loop-convert\"]]"

View File

@ -0,0 +1 @@
char const *const ManyQuotes("quotes:\'\'\'\'");

View File

@ -0,0 +1 @@
"[[\"warning\", \"escaped string literal can be written as a raw string literal\", \"modernize-raw-string-literal\"]]"

View File

@ -0,0 +1,5 @@
// modernize-redundant-void-arg
int foo(void) {
return 0;
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"redundant void argument list in function definition\", \"modernize-redundant-void-arg\"]]"

View File

@ -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);
}

View File

@ -0,0 +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\"]]"

View File

@ -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) {
}
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"use auto when declaring iterators\", \"modernize-use-auto\"]]"

View File

@ -0,0 +1,5 @@
void foo() {
bool p = 1;
bool f = static_cast<bool>(1);
bool x = p ? 1 : 0;
}

View File

@ -0,0 +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\"]]"

View File

@ -0,0 +1,6 @@
class IL {
public:
IL() {}
~IL() {}
};

View File

@ -0,0 +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\"]]"

View File

@ -0,0 +1,7 @@
struct PositivePrivate {
private:
PositivePrivate();
PositivePrivate(const PositivePrivate &);
PositivePrivate &operator=(PositivePrivate &&);
~PositivePrivate();
};

View File

@ -0,0 +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\"]]"

View File

@ -0,0 +1,5 @@
#define NULL 0
void f(void) {
char *str = NULL; // ok
(void)str;
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"use nullptr\", \"modernize-use-nullptr\"]]"

View File

@ -0,0 +1,8 @@
class Base {
public:
virtual void foo() = 0;
};
class Deriv : public Base {
void foo();
};

View File

@ -0,0 +1 @@
"[[\"warning\", \"annotate this function with 'override' or (rarely) 'final'\", \"modernize-use-override\"]]"

View File

@ -0,0 +1,6 @@
#include <string>
void foo() {
std::string str;
str.find("A");
}

View File

@ -0,0 +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\"]]"

View File

@ -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>>()) {
}
}

View File

@ -0,0 +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\"]]"

View File

@ -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);
}
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"string concatenation results in allocation of unnecessary temporary strings; consider using 'operator+=' or 'string::append()' instead\", \"performance-inefficient-string-concatenation\"]]"

View File

@ -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);
}
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"'push_back' is called inside a loop; consider pre-allocating the vector capacity before the loop\", \"performance-inefficient-vector-operation\"]]"

View File

@ -0,0 +1,7 @@
double acos(double);
void check_all_fns()
{
float a;
acos(a);
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"call to 'acos' promotes float to double\", \"performance-type-promotion-in-math-fn\"]]"

View File

@ -0,0 +1,7 @@
#include "structures.h"
extern const std::string& constReference();
void foo() {
const std::string UnnecessaryCopy = constReference();
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"the const qualified variable 'UnnecessaryCopy' is copy-constructed from a const reference; consider making it a const reference\", \"performance-unnecessary-copy-initialization\"]]"

View File

@ -0,0 +1,4 @@
#include "structures.h"
void f(const std::string Value) {
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"the const qualified parameter 'Value' is copied for each invocation; consider making it a reference\", \"performance-unnecessary-value-param\"]]"

View File

@ -0,0 +1,7 @@
#include "structures.h"
void foo() {
std::string a;
if (a.size())
return;
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"the 'empty' method should be used to check for emptiness instead of 'size'\", \"readability-container-size-empty\"]]"

View File

@ -0,0 +1,10 @@
void f() {
}
void foo() {
if (true)
return;
else
f();
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"do not use 'else' after 'return'\", \"readability-else-after-return\"]]"

View File

@ -0,0 +1,11 @@
void f()
{
}
void foo() {
if (1)
if (0)
f();
else
f();
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"different indentation for 'if' and corresponding 'else'\", \"readability-misleading-indentation\"]]"

View File

@ -0,0 +1,5 @@
extern void g();
void f() {
g();
return;
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"redundant return statement at the end of a function with a void return type\", \"readability-redundant-control-flow\"]]"

View File

@ -0,0 +1,11 @@
#include <memory>
struct A {
void f() {}
};
void foo() {
std::unique_ptr<A> ptr = std::make_unique<A>();
ptr.get()->f();
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"redundant get() call on smart pointer\", \"readability-redundant-smartptr-get\"]]"

View File

@ -0,0 +1,7 @@
#include "structures.h"
void foo() {
std::string a = "Mozilla";
std::string tmp;
tmp.assign(a.c_str());
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"redundant call to 'c_str'\", \"readability-redundant-string-cstr\"]]"

View File

@ -0,0 +1,5 @@
#include "structures.h"
int foo() {
std::string a = "";
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"redundant string initialization\", \"readability-redundant-string-init\"]]"

View File

@ -0,0 +1,6 @@
#include "structures.h"
int foo() {
std::unique_ptr<int> P;
delete P.release();
}

View File

@ -0,0 +1 @@
"[[\"warning\", \"prefer '= nullptr' to 'delete x.release()' to reset unique_ptr<> objects\", \"readability-uniqueptr-delete-release\"]]"

View File

@ -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()