[analyzer] Add --force-analyze-debug-code option to scan-build

to force debug build and hopefully enable more precise warnings.

Static Analyzer is much more efficient when built in debug mode
(-UNDEBUG) so we advice users to enable it manually. This may be
inconvenient in case of large complex projects (think about Linux
distros e.g. Android or Tizen). This patch adds a flag to scan-build
which inserts -UNDEBUG automatically.

Differential Revision: http://reviews.llvm.org/D16200


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261204 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Yury Gribov 2016-02-18 11:08:46 +00:00
Родитель dcd61b3089
Коммит 19b977bcdf
6 изменённых файлов: 62 добавлений и 7 удалений

Просмотреть файл

@ -106,7 +106,8 @@ def run_analyzer(args, output_dir):
'output_dir': output_dir,
'output_format': args.output_format,
'output_failures': args.output_failures,
'direct_args': analyzer_params(args)
'direct_args': analyzer_params(args),
'force_analyze_debug_code' : args.force_analyze_debug_code
}
logging.debug('run analyzer against compilation database')
@ -138,7 +139,9 @@ def setup_environment(args, destination, bin_dir):
'ANALYZE_BUILD_REPORT_DIR': destination,
'ANALYZE_BUILD_REPORT_FORMAT': args.output_format,
'ANALYZE_BUILD_REPORT_FAILURES': 'yes' if args.output_failures else '',
'ANALYZE_BUILD_PARAMETERS': ' '.join(analyzer_params(args))
'ANALYZE_BUILD_PARAMETERS': ' '.join(analyzer_params(args)),
'ANALYZE_BUILD_FORCE_ANALYZE_DEBUG_CODE'
: 'yes' if args.force_analyze_debug_code else ''
})
return environment
@ -168,6 +171,8 @@ def analyze_build_wrapper(cplusplus):
'output_failures': os.getenv('ANALYZE_BUILD_REPORT_FAILURES'),
'direct_args': os.getenv('ANALYZE_BUILD_PARAMETERS',
'').split(' '),
'force_analyze_debug_code':
os.getenv('ANALYZE_BUILD_FORCE_ANALYZE_DEBUG_CODE'),
'directory': os.getcwd(),
}
# get relevant parameters from command line arguments
@ -450,6 +455,13 @@ def create_parser(from_build_command):
Could be usefull when project contains 3rd party libraries.
The directory path shall be absolute path as file names in
the compilation database.""")
advanced.add_argument(
'--force-analyze-debug-code',
dest='force_analyze_debug_code',
action='store_true',
help="""Tells analyzer to enable assertions in code even if they were
disabled during compilation, enabling more precise
results.""")
plugins = parser.add_argument_group('checker options')
plugins.add_argument(

Просмотреть файл

@ -41,6 +41,7 @@ def require(required):
@require(['command', 'directory', 'file', # an entry from compilation database
'clang', 'direct_args', # compiler name, and arguments from command
'force_analyze_debug_code', # preprocessing options
'output_dir', 'output_format', 'output_failures'])
def run(opts):
""" Entry point to run (or not) static analyzer against a single entry
@ -164,9 +165,13 @@ def set_analyzer_output(opts, continuation=run_analyzer):
opts.update({'output': ['-o', opts['output_dir']]})
return continuation(opts)
def force_analyze_debug_code(cmd):
""" Enable assert()'s by undefining NDEBUG. """
cmd.append('-UNDEBUG')
@require(['file', 'directory', 'clang', 'direct_args', 'language',
'output_dir', 'output_format', 'output_failures'])
@require(['file', 'directory', 'clang', 'direct_args',
'force_analyze_debug_code', 'language', 'output_dir',
'output_format', 'output_failures'])
def create_commands(opts, continuation=set_analyzer_output):
""" Create command to run analyzer or failure report generation.
@ -178,6 +183,8 @@ def create_commands(opts, continuation=set_analyzer_output):
if 'arch' in opts:
common.extend(['-arch', opts.pop('arch')])
common.extend(opts.pop('compile_options', []))
if opts['force_analyze_debug_code']:
force_analyze_debug_code(common)
common.extend(['-x', opts['language']])
common.append(os.path.relpath(opts['file'], opts['directory']))

Просмотреть файл

@ -211,3 +211,14 @@ class RequireDecoratorTest(unittest.TestCase):
def test_method_exception_not_caught(self):
self.assertRaises(Exception, method_exception_from_inside, dict())
class ForceAnalyzeDebugTest(unittest.TestCase):
def test_force_analyze_debug_code(self):
for a, b in [
([], ['-UNDEBUG']),
(['-O2'], ['-O2', '-UNDEBUG']),
(['-Dkey=val'], ['-Dkey=val', '-UNDEBUG']),
(['-D', 'NDEBUG'], ['-D', 'NDEBUG', '-UNDEBUG']) ]:
sut.force_analyze_debug_code(a)
self.assertEqual(a, b)

Просмотреть файл

@ -69,7 +69,8 @@ my %Options = (
MaxLoop => 0,
PluginsToLoad => [],
AnalyzerDiscoveryMethod => undef,
OverrideCompiler => 0 # The flag corresponding to the --override-compiler command line option.
OverrideCompiler => 0, # The flag corresponding to the --override-compiler command line option.
ForceAnalyzeDebugCode => 0
);
lock_keys(%Options);
@ -951,7 +952,8 @@ sub SetEnv {
'CCC_CC',
'CCC_CXX',
'CCC_REPORT_FAILURES',
'CLANG_ANALYZER_TARGET') {
'CLANG_ANALYZER_TARGET',
'CCC_ANALYZER_FORCE_ANALYZE_DEBUG_CODE') {
my $x = $EnvVars->{$var};
if (defined $x) { $ENV{$var} = $x }
}
@ -1118,6 +1120,11 @@ OPTIONS:
Also analyze functions in #included files. By default, such functions
are skipped unless they are called by functions within the main source file.
--force-analyze-debug-code
Tells analyzer to enable assertions in code even if they were disabled
during compilation to enable more precise results.
-o <output location>
Specifies the output directory for analyzer reports. Subdirectories will be
@ -1681,6 +1688,12 @@ sub ProcessArgs {
next;
}
if ($arg eq "--force-analyze-debug-code") {
shift @$Args;
$Options{ForceAnalyzeDebugCode} = 1;
next;
}
DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/);
$NumArgs--;
@ -1796,7 +1809,8 @@ my %EnvVars = (
'CCC_ANALYZER_CONSTRAINTS_MODEL' => $Options{ConstraintsModel},
'CCC_ANALYZER_INTERNAL_STATS' => $Options{InternalStats},
'CCC_ANALYZER_OUTPUT_FORMAT' => $Options{OutputFormat},
'CLANG_ANALYZER_TARGET' => $Options{AnalyzerTarget}
'CLANG_ANALYZER_TARGET' => $Options{AnalyzerTarget},
'CCC_ANALYZER_FORCE_ANALYZE_DEBUG_CODE' => $Options{ForceAnalyzeDebugCode}
);
# Run the build.

Просмотреть файл

@ -492,6 +492,9 @@ if (defined $ENV{'CCC_ANALYZER_LOG'}) { $Verbose = 2; }
# Get the HTML output directory.
my $HtmlDir = $ENV{'CCC_ANALYZER_HTML'};
# Get force-analyze-debug-code option.
my $ForceAnalyzeDebugCode = $ENV{'CCC_ANALYZER_FORCE_ANALYZE_DEBUG_CODE'};
my %DisabledArchs = ('ppc' => 1, 'ppc64' => 1);
my %ArchsSeen;
my $HadArch = 0;
@ -682,6 +685,11 @@ foreach (my $i = 0; $i < scalar(@ARGV); ++$i) {
}
}
# Forcedly enable debugging if requested by user.
if ($ForceAnalyzeDebugCode) {
push @CompileOpts, '-UNDEBUG';
}
# If we are on OSX and have an installation where the
# default SDK is inferred by xcrun use xcrun to infer
# the SDK.

Просмотреть файл

@ -226,6 +226,9 @@ Assertions are picked up by the static analyzer to prune infeasible paths, which
in some cases can greatly reduce the number of false positives (bogus error
reports) emitted by the tool.</p>
<p>Another option is to use <tt>--force-analyze-debug-code</tt> flag of
<b>scan-build</b> tool which would enable assertions automatically.</p>
<h3 id="recommend_verbose">Use verbose output when debugging scan-build</h3>
<p><tt>scan-build</tt> takes a <b>-v</b> option to emit verbose output about