19cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek#!/usr/bin/env perl 29cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 39cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# The LLVM Compiler Infrastructure 49cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 59cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# This file is distributed under the University of Illinois Open Source 69cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# License. See LICENSE.TXT for details. 79cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 89cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##===----------------------------------------------------------------------===## 99cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# A script designed to wrap a build so that all calls to gcc are intercepted 119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# and piped to the static analyzer. 129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# 139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##===----------------------------------------------------------------------===## 149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekuse strict; 169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekuse warnings; 1722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenekuse FindBin qw($RealBin); 18a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenekuse Digest::MD5; 197a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekuse File::Basename; 209d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenekuse File::Find; 2123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenekuse Term::ANSIColor; 2223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenekuse Term::ANSIColor qw(:constants); 23cd25c13ade3afa829c87ca1ed0ed0d379f426251Ted Kremenekuse Cwd qw/ getcwd abs_path /; 247cba11262458df05951432b54997eb40a35dbf9eTed Kremenekuse Sys::Hostname; 259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Verbose = 0; # Verbose output from this script. 279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $Prog = "scan-build"; 28f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildName; 29f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekmy $BuildDate; 309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 310e6893840fdd69a8a4d6561663a5a29af237ae08Ted Kremenekmy $TERM = $ENV{'TERM'}; 32c9480dd03522f0bab5fff7d30402cb7ee31117dcTed Kremenekmy $UseColor = (defined $TERM and $TERM =~ 'xterm-.*color' and -t STDOUT 330e6893840fdd69a8a4d6561663a5a29af237ae08Ted Kremenek and defined $ENV{'SCAN_BUILD_COLOR'}); 3423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 357cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $UserName = HtmlEscape(getpwuid($<) || 'unknown'); 367cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $HostName = HtmlEscape(hostname() || 'unknown'); 377cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $CurrentDir = HtmlEscape(getcwd()); 387cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $CurrentDirSuffix = basename($CurrentDir); 397cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 40f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaksmy @PluginsToLoad; 417cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $CmdArgs; 427cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 437cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $HtmlTitle; 447cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 457cba11262458df05951432b54997eb40a35dbf9eTed Kremenekmy $Date = localtime(); 467cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 47b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------## 48b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek# Diagnostics 49b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------## 50b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 5123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremeneksub Diag { 5223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek if ($UseColor) { 5323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print BOLD, MAGENTA "$Prog: @_"; 5423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print RESET; 5523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 5623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek else { 5723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print "$Prog: @_"; 5823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 5923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek} 6023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 61991c54b9b7409656e5593364e065878b5210d556Ted Kremeneksub DiagCrashes { 62991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $Dir = shift; 63938eef139ad43345248235da31f78a759dd18f13Ted Kremenek Diag ("The analyzer encountered problems on some source files.\n"); 64938eef139ad43345248235da31f78a759dd18f13Ted Kremenek Diag ("Preprocessed versions of these sources were deposited in '$Dir/failures'.\n"); 65991c54b9b7409656e5593364e065878b5210d556Ted Kremenek Diag ("Please consider submitting a bug report using these files:\n"); 66e2c8663ad2b110712401145b866072bb94108058Nico Weber Diag (" http://clang-analyzer.llvm.org/filing_bugs.html\n") 67991c54b9b7409656e5593364e065878b5210d556Ted Kremenek} 68991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 6923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremeneksub DieDiag { 7023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek if ($UseColor) { 7123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print BOLD, RED "$Prog: "; 7223cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print RESET, RED @_; 7323cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print RESET; 7423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 7523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek else { 7623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek print "$Prog: ", @_; 7723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek } 7823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek exit(0); 7923cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek} 8023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek 819cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 828db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek# Print default checker names 838db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek##----------------------------------------------------------------------------## 848db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek 858db26ce0464c712058ab60b72e2a70c04148020eTed Kremenekif (grep /^--help-checkers$/, @ARGV) { 868db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek my @options = qx($0 -h); 878db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek foreach (@options) { 888db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek next unless /^ \+/; 898db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek s/^\s*//; 908db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek my ($sign, $name, @text) = split ' ', $_; 918db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek print $name, $/ if $sign eq '+'; 928db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek } 938db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek exit 1; 948db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek} 958db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek 968db26ce0464c712058ab60b72e2a70c04148020eTed Kremenek##----------------------------------------------------------------------------## 97810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek# Declaration of Clang options. Populated later. 98b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------## 99b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 100e01ca51f4167b5a7fd1d6230f2e2f1f177fd68e3Ted Kremenekmy $Clang; 101810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenekmy $ClangSB; 102810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenekmy $ClangCXX; 103810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenekmy $ClangVersion; 104fd9df0eddd7d2b190f740f33a3d08f611c0be3f0Ted Kremenek 105b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek##----------------------------------------------------------------------------## 106fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek# GetHTMLRunDir - Construct an HTML directory name for the current sub-run. 1079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 1089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 109a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub GetHTMLRunDir { 110fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek die "Not enough arguments." if (@_ == 0); 1112a3a8b9f47b0a8f3fdd57bc4fbd08684feb4fa85Ted Kremenek my $Dir = shift @_; 112fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek my $TmpMode = 0; 113fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (!defined $Dir) { 1143fa3c44d624d2df9ef2649ca1a7efa97d81b36d8Jordan Rose $Dir = $ENV{'TMPDIR'}; 1153fa3c44d624d2df9ef2649ca1a7efa97d81b36d8Jordan Rose if (!defined $Dir) { $Dir = "/tmp"; } 116fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek $TmpMode = 1; 117fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 118bf762c9b48673e9686a97fe6ca144d891316164eTed Kremenek 119bf762c9b48673e9686a97fe6ca144d891316164eTed Kremenek # Chop off any trailing '/' characters. 120bf762c9b48673e9686a97fe6ca144d891316164eTed Kremenek while ($Dir =~ /\/$/) { chop $Dir; } 121fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1229cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Get current date and time. 1232a3a8b9f47b0a8f3fdd57bc4fbd08684feb4fa85Ted Kremenek my @CurrentTime = localtime(); 1249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $year = $CurrentTime[5] + 1900; 1259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $day = $CurrentTime[3]; 1269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $month = $CurrentTime[4] + 1; 1279d7405fafd5bc08d38bc75579927bf414570bd61Ted Kremenek my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day); 1289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1292a3a8b9f47b0a8f3fdd57bc4fbd08684feb4fa85Ted Kremenek # Determine the run number. 1309cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $RunNumber; 1319cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1322a3a8b9f47b0a8f3fdd57bc4fbd08684feb4fa85Ted Kremenek if (-d $Dir) { 1339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -r $Dir) { 13423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("directory '$Dir' exists but is not readable.\n"); 1352a3a8b9f47b0a8f3fdd57bc4fbd08684feb4fa85Ted Kremenek } 1362a3a8b9f47b0a8f3fdd57bc4fbd08684feb4fa85Ted Kremenek # Iterate over all files in the specified directory. 1372a3a8b9f47b0a8f3fdd57bc4fbd08684feb4fa85Ted Kremenek my $max = 0; 1389cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek opendir(DIR, $Dir); 13929da6c59df7ca994e75139303a9230b24e2abaadTed Kremenek my @FILES = grep { -d "$Dir/$_" } readdir(DIR); 1409cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek closedir(DIR); 1419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1422a3a8b9f47b0a8f3fdd57bc4fbd08684feb4fa85Ted Kremenek foreach my $f (@FILES) { 143fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek # Strip the prefix '$Prog-' if we are dumping files to /tmp. 144fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if ($TmpMode) { 145fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek next if (!($f =~ /^$Prog-(.+)/)); 146fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek $f = $1; 147fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 148fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1499cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my @x = split/-/, $f; 1509cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if (scalar(@x) != 4); 1519cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[0] != $year); 1529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[1] != $month); 1539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next if ($x[2] != $day); 1549cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1559cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($x[3] > $max) { 1569cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $max = $x[3]; 1579cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1589cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1599cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1609cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = $max + 1; 1619cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1629cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek else { 1639cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1649cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (-x $Dir) { 16523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("'$Dir' exists but is not a directory.\n"); 1669cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 167fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 168fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if ($TmpMode) { 169445fa776d2bc9207c33a9b9ab4afb9513f6b81b0Ted Kremenek DieDiag("The directory '/tmp' does not exist or cannot be accessed.\n"); 170fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 171fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # $Dir does not exist. It will be automatically created by the 1739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # clang driver. Set the run number to 1. 174fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek 1759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $RunNumber = 1; 1769cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 1779cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 178fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek die "RunNumber must be defined!" if (!defined $RunNumber); 1799cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1809cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Append the run number. 181fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek my $NewDir; 182fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if ($TmpMode) { 183fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek $NewDir = "$Dir/$Prog-$DateString-$RunNumber"; 184fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 185fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek else { 186fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek $NewDir = "$Dir/$DateString-$RunNumber"; 187fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek } 188fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek system 'mkdir','-p',$NewDir; 189fc0898a6529f3d6bc9a4effdb3202aee13170fe3Ted Kremenek return $NewDir; 1909cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 1919cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 192a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub SetHtmlEnv { 1939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1949cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "Wrong number of arguments." if (scalar(@_) != 2); 1959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1969cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Args = shift; 1979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Dir = shift; 1989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek die "No build command." if (scalar(@$Args) == 0); 2009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $Cmd = $$Args[0]; 2029e4a1bb0084bf3bf64595f57effe496cb2cf1863Ted Kremenek 2039e4a1bb0084bf3bf64595f57effe496cb2cf1863Ted Kremenek if ($Cmd =~ /configure/ || $Cmd =~ /autogen/) { 2049cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek return; 2059cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 2069cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($Verbose) { 20823cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("Emitting reports for this run to '$Dir'.\n"); 2099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 2109cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $ENV{'CCC_ANALYZER_HTML'} = $Dir; 2129cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 2139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 2149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 21557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# ComputeDigest - Compute a digest of the specified file. 21657cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 21757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 21857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremeneksub ComputeDigest { 21957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $FName = shift; 22023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName); 221a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 222a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek # Use Digest::MD5. We don't have to be cryptographically secure. We're 2237ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek # just looking for duplicate files that come from a non-malicious source. 2247ea02e6822fadcda31014c55f58cbc04e24d5abfTed Kremenek # We use Digest::MD5 because it is a standard Perl module that should 22563c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek # come bundled on most systems. 22623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n"); 227a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek binmode FILE; 228a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest; 229a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek close(FILE); 230a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek 23163c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek # Return the digest. 232a6e24811207ad2179b0dabe3d7e6ec551e6686dfTed Kremenek return $Result; 23357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek} 23457cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 23557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek##----------------------------------------------------------------------------## 2367a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek# UpdatePrefix - Compute the common prefix of files. 2377a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2387a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2397a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenekmy $Prefix; 2407a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2417a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdatePrefix { 2427a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $x = shift; 2437a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $y = basename($x); 2447a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $x =~ s/\Q$y\E$//; 2457a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2467a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek if (!defined $Prefix) { 2477a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek $Prefix = $x; 2487a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return; 2497a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 2507a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 25120b2bae90c102f405ba70f602c45660ce1cd0c4eTed Kremenek chop $Prefix while (!($x =~ /^\Q$Prefix/)); 2527a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 2537a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2547a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub GetPrefix { 2557a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek return $Prefix; 2567a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 2577a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2587a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2597a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek# UpdateInFilePath - Update the path in the report file. 2607a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2617a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2627a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremeneksub UpdateInFilePath { 2637a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $fname = shift; 2647a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $regex = shift; 2657a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek my $newtext = shift; 26663c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek 2677a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek open (RIN, $fname) or die "cannot open $fname"; 26863c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek open (ROUT, ">", "$fname.tmp") or die "cannot open $fname.tmp"; 26963c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek 2707a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek while (<RIN>) { 2717a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek s/$regex/$newtext/; 2727a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek print ROUT $_; 2737a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek } 27463c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek 2757a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek close (ROUT); 2767a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek close (RIN); 27720161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system("mv", "$fname.tmp", $fname); 2787a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek} 2797a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 2807a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek##----------------------------------------------------------------------------## 2814f2b10b24bab0049020d268382eda144e2aa064cTom Care# AddStatLine - Decode and insert a statistics line into the database. 2824f2b10b24bab0049020d268382eda144e2aa064cTom Care##----------------------------------------------------------------------------## 2834f2b10b24bab0049020d268382eda144e2aa064cTom Care 2844f2b10b24bab0049020d268382eda144e2aa064cTom Caresub AddStatLine { 2854f2b10b24bab0049020d268382eda144e2aa064cTom Care my $Line = shift; 2864f2b10b24bab0049020d268382eda144e2aa064cTom Care my $Stats = shift; 2874a374f9a58a5b350ec2e4123b20c9884ed1f5f15Jordan Rose my $File = shift; 2884f2b10b24bab0049020d268382eda144e2aa064cTom Care 2894f2b10b24bab0049020d268382eda144e2aa064cTom Care print $Line . "\n"; 2904f2b10b24bab0049020d268382eda144e2aa064cTom Care 2914a374f9a58a5b350ec2e4123b20c9884ed1f5f15Jordan Rose my $Regex = qr/(.*?)\ ->\ Total\ CFGBlocks:\ (\d+)\ \|\ Unreachable 2926bdda82234ff106d561dc8c0ce5ca48b97726bbfTed Kremenek \ CFGBlocks:\ (\d+)\ \|\ Exhausted\ Block:\ (yes|no)\ \|\ Empty\ WorkList: 2934f2b10b24bab0049020d268382eda144e2aa064cTom Care \ (yes|no)/x; 2944f2b10b24bab0049020d268382eda144e2aa064cTom Care 2954f2b10b24bab0049020d268382eda144e2aa064cTom Care if ($Line !~ $Regex) { 2964f2b10b24bab0049020d268382eda144e2aa064cTom Care return; 2974f2b10b24bab0049020d268382eda144e2aa064cTom Care } 2984f2b10b24bab0049020d268382eda144e2aa064cTom Care 2994f2b10b24bab0049020d268382eda144e2aa064cTom Care # Create a hash of the interesting fields 3004f2b10b24bab0049020d268382eda144e2aa064cTom Care my $Row = { 3014a374f9a58a5b350ec2e4123b20c9884ed1f5f15Jordan Rose Filename => $File, 3024a374f9a58a5b350ec2e4123b20c9884ed1f5f15Jordan Rose Function => $1, 3034a374f9a58a5b350ec2e4123b20c9884ed1f5f15Jordan Rose Total => $2, 3044a374f9a58a5b350ec2e4123b20c9884ed1f5f15Jordan Rose Unreachable => $3, 3054a374f9a58a5b350ec2e4123b20c9884ed1f5f15Jordan Rose Aborted => $4, 3064a374f9a58a5b350ec2e4123b20c9884ed1f5f15Jordan Rose Empty => $5 3074f2b10b24bab0049020d268382eda144e2aa064cTom Care }; 3084f2b10b24bab0049020d268382eda144e2aa064cTom Care 3094f2b10b24bab0049020d268382eda144e2aa064cTom Care # Add them to the stats array 3104f2b10b24bab0049020d268382eda144e2aa064cTom Care push @$Stats, $Row; 3114f2b10b24bab0049020d268382eda144e2aa064cTom Care} 3124f2b10b24bab0049020d268382eda144e2aa064cTom Care 3134f2b10b24bab0049020d268382eda144e2aa064cTom Care##----------------------------------------------------------------------------## 3145744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek# ScanFile - Scan a report file for various identifying attributes. 3155744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 3165744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 31757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# Sometimes a source file is scanned more than once, and thus produces 31857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek# multiple error reports. We use a cache to solve this problem. 31957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 32057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenekmy %AlreadyScanned; 32157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 3225744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremeneksub ScanFile { 3235744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3245744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Index = shift; 3255744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $Dir = shift; 3265744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek my $FName = shift; 3274f2b10b24bab0049020d268382eda144e2aa064cTom Care my $Stats = shift; 3285744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 32957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Compute a digest for the report file. Determine if we have already 33057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # scanned a file that looks just like it. 33157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 33257cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek my $digest = ComputeDigest("$Dir/$FName"); 33357cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 334fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $AlreadyScanned{$digest}) { 33557cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek # Redundant file. Remove it. 33620161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system ("rm", "-f", "$Dir/$FName"); 33757cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek return; 33857cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek } 33957cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 34057cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek $AlreadyScanned{$digest} = 1; 34157cf446d344bb2649e8742cedf1cf4342ed78aa9Ted Kremenek 342809709f46f2516b4054681f0b76284055a84a50fTed Kremenek # At this point the report file is not world readable. Make it happen. 34320161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system ("chmod", "644", "$Dir/$FName"); 344684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek 345684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenek # Scan the report file for tags. 34623cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n"); 3475744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3484f2b10b24bab0049020d268382eda144e2aa064cTom Care my $BugType = ""; 3494f2b10b24bab0049020d268382eda144e2aa064cTom Care my $BugFile = ""; 3504f2b10b24bab0049020d268382eda144e2aa064cTom Care my $BugCategory = ""; 3514f2b10b24bab0049020d268382eda144e2aa064cTom Care my $BugDescription = ""; 3524f2b10b24bab0049020d268382eda144e2aa064cTom Care my $BugPathLength = 1; 3534f2b10b24bab0049020d268382eda144e2aa064cTom Care my $BugLine = 0; 354ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 3555744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek while (<IN>) { 356d658e67b438c60fbe3bd1773a3172fd0f082c483Ted Kremenek last if (/<!-- BUGMETAEND -->/); 357ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 358a26ddabc0eb8cf8ea4de1878f84d3b920fc2349fTed Kremenek if (/<!-- BUGTYPE (.*) -->$/) { 359a26ddabc0eb8cf8ea4de1878f84d3b920fc2349fTed Kremenek $BugType = $1; 3605744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 36122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGFILE (.*) -->$/) { 362990c2f45e566d8ff097fa90176ba90036892b3cdTed Kremenek $BugFile = abs_path($1); 3637a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek UpdatePrefix($BugFile); 36422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 36522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGPATHLENGTH (.*) -->$/) { 36622d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugPathLength = $1; 36722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 36822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek elsif (/<!-- BUGLINE (.*) -->$/) { 36922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek $BugLine = $1; 370ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek } 371ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek elsif (/<!-- BUGCATEGORY (.*) -->$/) { 372ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek $BugCategory = $1; 37322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek } 3744f2b10b24bab0049020d268382eda144e2aa064cTom Care elsif (/<!-- BUGDESC (.*) -->$/) { 3754f2b10b24bab0049020d268382eda144e2aa064cTom Care $BugDescription = $1; 3764f2b10b24bab0049020d268382eda144e2aa064cTom Care } 3775744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 3785744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 3795744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(IN); 380ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 381ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek if (!defined $BugCategory) { 382ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek $BugCategory = "Other"; 383ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek } 3844f2b10b24bab0049020d268382eda144e2aa064cTom Care 3854f2b10b24bab0049020d268382eda144e2aa064cTom Care # Don't add internal statistics to the bug reports 3864f2b10b24bab0049020d268382eda144e2aa064cTom Care if ($BugCategory =~ /statistics/i) { 3874a374f9a58a5b350ec2e4123b20c9884ed1f5f15Jordan Rose AddStatLine($BugDescription, $Stats, $BugFile); 3884f2b10b24bab0049020d268382eda144e2aa064cTom Care return; 3894f2b10b24bab0049020d268382eda144e2aa064cTom Care } 3904f2b10b24bab0049020d268382eda144e2aa064cTom Care 391a26ddabc0eb8cf8ea4de1878f84d3b920fc2349fTed Kremenek push @$Index,[ $FName, $BugCategory, $BugType, $BugFile, $BugLine, 39281983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek $BugPathLength ]; 39322d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek} 39422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 39522d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 3963ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek# CopyFiles - Copy resource files to target directory. 39722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek##----------------------------------------------------------------------------## 39822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 3993ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremeneksub CopyFiles { 40022d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 40122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek my $Dir = shift; 402e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek 403e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek my $JS = Cwd::realpath("$RealBin/sorttable.js"); 40422d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 40523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Cannot find 'sorttable.js'.\n") 406e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek if (! -r $JS); 40722d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 408e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek system ("cp", $JS, "$Dir"); 40922d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek 41023cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n") 41122d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek if (! -r "$Dir/sorttable.js"); 4123ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek 413e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek my $CSS = Cwd::realpath("$RealBin/scanview.css"); 414e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek 4153ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek DieDiag("Cannot find 'scanview.css'.\n") 416e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek if (! -r $CSS); 4173ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek 418e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek system ("cp", $CSS, "$Dir"); 4193ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek 4203ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek DieDiag("Could not copy 'scanview.css' to '$Dir'.\n") 421e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek if (! -r $CSS); 4225744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek} 4235744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 4245744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek##----------------------------------------------------------------------------## 4254f2b10b24bab0049020d268382eda144e2aa064cTom Care# CalcStats - Calculates visitation statistics and returns the string. 4264f2b10b24bab0049020d268382eda144e2aa064cTom Care##----------------------------------------------------------------------------## 4274f2b10b24bab0049020d268382eda144e2aa064cTom Care 4284f2b10b24bab0049020d268382eda144e2aa064cTom Caresub CalcStats { 4294f2b10b24bab0049020d268382eda144e2aa064cTom Care my $Stats = shift; 4304f2b10b24bab0049020d268382eda144e2aa064cTom Care 4314f2b10b24bab0049020d268382eda144e2aa064cTom Care my $TotalBlocks = 0; 4324f2b10b24bab0049020d268382eda144e2aa064cTom Care my $UnreachedBlocks = 0; 4334f2b10b24bab0049020d268382eda144e2aa064cTom Care my $TotalFunctions = scalar(@$Stats); 4344f2b10b24bab0049020d268382eda144e2aa064cTom Care my $BlockAborted = 0; 4354f2b10b24bab0049020d268382eda144e2aa064cTom Care my $WorkListAborted = 0; 4364f2b10b24bab0049020d268382eda144e2aa064cTom Care my $Aborted = 0; 4374f2b10b24bab0049020d268382eda144e2aa064cTom Care 4384f2b10b24bab0049020d268382eda144e2aa064cTom Care # Calculate the unique files 4394f2b10b24bab0049020d268382eda144e2aa064cTom Care my $FilesHash = {}; 4404f2b10b24bab0049020d268382eda144e2aa064cTom Care 4414f2b10b24bab0049020d268382eda144e2aa064cTom Care foreach my $Row (@$Stats) { 4424f2b10b24bab0049020d268382eda144e2aa064cTom Care $FilesHash->{$Row->{Filename}} = 1; 4434f2b10b24bab0049020d268382eda144e2aa064cTom Care $TotalBlocks += $Row->{Total}; 4444f2b10b24bab0049020d268382eda144e2aa064cTom Care $UnreachedBlocks += $Row->{Unreachable}; 4454f2b10b24bab0049020d268382eda144e2aa064cTom Care $BlockAborted++ if $Row->{Aborted} eq 'yes'; 4464f2b10b24bab0049020d268382eda144e2aa064cTom Care $WorkListAborted++ if $Row->{Empty} eq 'no'; 4474f2b10b24bab0049020d268382eda144e2aa064cTom Care $Aborted++ if $Row->{Aborted} eq 'yes' || $Row->{Empty} eq 'no'; 4484f2b10b24bab0049020d268382eda144e2aa064cTom Care } 4494f2b10b24bab0049020d268382eda144e2aa064cTom Care 4504f2b10b24bab0049020d268382eda144e2aa064cTom Care my $TotalFiles = scalar(keys(%$FilesHash)); 4514f2b10b24bab0049020d268382eda144e2aa064cTom Care 4524f2b10b24bab0049020d268382eda144e2aa064cTom Care # Calculations 4534f2b10b24bab0049020d268382eda144e2aa064cTom Care my $PercentAborted = sprintf("%.2f", $Aborted / $TotalFunctions * 100); 4544f2b10b24bab0049020d268382eda144e2aa064cTom Care my $PercentBlockAborted = sprintf("%.2f", $BlockAborted / $TotalFunctions 4554f2b10b24bab0049020d268382eda144e2aa064cTom Care * 100); 4564f2b10b24bab0049020d268382eda144e2aa064cTom Care my $PercentWorkListAborted = sprintf("%.2f", $WorkListAborted / 4574f2b10b24bab0049020d268382eda144e2aa064cTom Care $TotalFunctions * 100); 4584f2b10b24bab0049020d268382eda144e2aa064cTom Care my $PercentBlocksUnreached = sprintf("%.2f", $UnreachedBlocks / $TotalBlocks 4594f2b10b24bab0049020d268382eda144e2aa064cTom Care * 100); 4604f2b10b24bab0049020d268382eda144e2aa064cTom Care 4614f2b10b24bab0049020d268382eda144e2aa064cTom Care my $StatsString = "Analyzed $TotalBlocks blocks in $TotalFunctions functions" 4624f2b10b24bab0049020d268382eda144e2aa064cTom Care . " in $TotalFiles files\n" 4634f2b10b24bab0049020d268382eda144e2aa064cTom Care . "$Aborted functions aborted early ($PercentAborted%)\n" 4644f2b10b24bab0049020d268382eda144e2aa064cTom Care . "$BlockAborted had aborted blocks ($PercentBlockAborted%)\n" 4654f2b10b24bab0049020d268382eda144e2aa064cTom Care . "$WorkListAborted had unfinished worklists ($PercentWorkListAborted%)\n" 4664f2b10b24bab0049020d268382eda144e2aa064cTom Care . "$UnreachedBlocks blocks were never reached ($PercentBlocksUnreached%)\n"; 4674f2b10b24bab0049020d268382eda144e2aa064cTom Care 4684f2b10b24bab0049020d268382eda144e2aa064cTom Care return $StatsString; 4694f2b10b24bab0049020d268382eda144e2aa064cTom Care} 4704f2b10b24bab0049020d268382eda144e2aa064cTom Care 4714f2b10b24bab0049020d268382eda144e2aa064cTom Care##----------------------------------------------------------------------------## 4729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Postprocess - Postprocess the results of an analysis scan. 4739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 4749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4759d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenekmy @filesFound; 4769d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenekmy $baseDir; 4779d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremeneksub FileWanted { 4789d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek my $baseDirRegEx = quotemeta $baseDir; 4799d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek my $file = $File::Find::name; 4809d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek if ($file =~ /report-.*\.html$/) { 4819d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek my $relative_file = $file; 4829d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek $relative_file =~ s/$baseDirRegEx//g; 4839d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek push @filesFound, $relative_file; 4849d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek } 4859d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek} 4869d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek 487a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub Postprocess { 4889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4894f2b10b24bab0049020d268382eda144e2aa064cTom Care my $Dir = shift; 4904f2b10b24bab0049020d268382eda144e2aa064cTom Care my $BaseDir = shift; 4914f2b10b24bab0049020d268382eda144e2aa064cTom Care my $AnalyzerStats = shift; 49233e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose my $KeepEmpty = shift; 4939cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 494fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek die "No directory specified." if (!defined $Dir); 4959cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 4969cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (! -d $Dir) { 49723cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("No bugs found.\n"); 498363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek return 0; 4999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 5009cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 5019d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek $baseDir = $Dir . "/"; 5029d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek find({ wanted => \&FileWanted, follow => 0}, $Dir); 5039d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek 5049d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek if (scalar(@filesFound) == 0 and ! -e "$Dir/failures") { 50533e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose if (! $KeepEmpty) { 50633e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose Diag("Removing directory '$Dir' because it contains no reports.\n"); 50733e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose system ("rm", "-fR", $Dir); 50833e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose } 509e09b8c41d0eeb17f8cbe73affb213cb7ff8d0718Jordan Rose Diag("No bugs found.\n"); 510363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek return 0; 5119cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 5125744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 513991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Scan each report file and build an index. 5144f2b10b24bab0049020d268382eda144e2aa064cTom Care my @Index; 5154f2b10b24bab0049020d268382eda144e2aa064cTom Care my @Stats; 5169d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek foreach my $file (@filesFound) { ScanFile(\@Index, $Dir, $file, \@Stats); } 5175744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 518938eef139ad43345248235da31f78a759dd18f13Ted Kremenek # Scan the failures directory and use the information in the .info files 519d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek # to update the common prefix directory. 520938eef139ad43345248235da31f78a759dd18f13Ted Kremenek my @failures; 521938eef139ad43345248235da31f78a759dd18f13Ted Kremenek my @attributes_ignored; 522938eef139ad43345248235da31f78a759dd18f13Ted Kremenek if (-d "$Dir/failures") { 523938eef139ad43345248235da31f78a759dd18f13Ted Kremenek opendir(DIR, "$Dir/failures"); 524938eef139ad43345248235da31f78a759dd18f13Ted Kremenek @failures = grep { /[.]info.txt$/ && !/attribute_ignored/; } readdir(DIR); 525d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek closedir(DIR); 526938eef139ad43345248235da31f78a759dd18f13Ted Kremenek opendir(DIR, "$Dir/failures"); 527938eef139ad43345248235da31f78a759dd18f13Ted Kremenek @attributes_ignored = grep { /^attribute_ignored/; } readdir(DIR); 528938eef139ad43345248235da31f78a759dd18f13Ted Kremenek closedir(DIR); 529938eef139ad43345248235da31f78a759dd18f13Ted Kremenek foreach my $file (@failures) { 530938eef139ad43345248235da31f78a759dd18f13Ted Kremenek open IN, "$Dir/failures/$file" or DieDiag("cannot open $file\n"); 531d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek my $Path = <IN>; 532d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek if (defined $Path) { UpdatePrefix($Path); } 533d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek close IN; 534d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek } 535d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek } 536d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek 53763c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek # Generate an index.html file. 53863c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek my $FName = "$Dir/index.html"; 53963c2017737530a7009f709f2fe822f20f63930b1Ted Kremenek open(OUT, ">", $FName) or DieDiag("Cannot create file '$FName'\n"); 5405744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 5416e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the header. 5426e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 5435744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint OUT <<ENDTEXT; 5445744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<html> 5455744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek<head> 5467cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<title>${HtmlTitle}</title> 547f143545ce5ce125e7c1aa6fca9df372bfb604e9cTed Kremenek<link type="text/css" rel="stylesheet" href="scanview.css"/> 54822d6a639ce04ababc6900ea8b50ed7167db0f39cTed Kremenek<script src="sorttable.js"></script> 5496e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<script language='javascript' type="text/javascript"> 5506e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction SetDisplay(RowClass, DisplayVal) 5516e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek{ 5526e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek var Rows = document.getElementsByTagName("tr"); 5536e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek for ( var i = 0 ; i < Rows.length; ++i ) { 5546e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (Rows[i].className == RowClass) { 5556e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek Rows[i].style.display = DisplayVal; 5566e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 5576e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 5586e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 559ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 5602350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenekfunction CopyCheckedStateToCheckButtons(SummaryCheckButton) { 5612350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek var Inputs = document.getElementsByTagName("input"); 5622350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek for ( var i = 0 ; i < Inputs.length; ++i ) { 5632350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek if (Inputs[i].type == "checkbox") { 5642350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek if(Inputs[i] != SummaryCheckButton) { 5652350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek Inputs[i].checked = SummaryCheckButton.checked; 5662350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek Inputs[i].onclick(); 5672350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek } 5682350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek } 5692350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek } 5702350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek} 5712350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek 572999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenekfunction returnObjById( id ) { 573999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek if (document.getElementById) 574999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek var returnVar = document.getElementById(id); 575999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek else if (document.all) 576999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek var returnVar = document.all[id]; 577999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek else if (document.layers) 578999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek var returnVar = document.layers[id]; 579999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek return returnVar; 580999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek} 581999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek 582999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenekvar NumUnchecked = 0; 583999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek 5846e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekfunction ToggleDisplay(CheckButton, ClassName) { 5856e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek if (CheckButton.checked) { 5866e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, ""); 587999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek if (--NumUnchecked == 0) { 588999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek returnObjById("AllBugsCheck").checked = true; 589999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek } 5906e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 5916e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek else { 5926e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek SetDisplay(ClassName, "none"); 593999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek NumUnchecked++; 594999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek returnObjById("AllBugsCheck").checked = false; 5956e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 5966e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek} 5976e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</script> 5981d1abb1dec3d0b7609809d876a16a64a021e96e7Ted Kremenek<!-- SUMMARYENDHEAD --> 5996e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</head> 6006e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek<body> 6017cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<h1>${HtmlTitle}</h1> 6027cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 6037cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<table> 6047cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>User:</th><td>${UserName}\@${HostName}</td></tr> 6057cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Working Directory:</th><td>${CurrentDir}</td></tr> 6067cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Command Line:</th><td>${CmdArgs}</td></tr> 607b4882d50923881d1a01af4d5604b5baaa141cdf9Douglas Gregor<tr><th>Clang Version:</th><td>${ClangVersion}</td></tr> 6087cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<tr><th>Date:</th><td>${Date}</td></tr> 6097cba11262458df05951432b54997eb40a35dbf9eTed KremenekENDTEXT 6107cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 6117cba11262458df05951432b54997eb40a35dbf9eTed Kremenekprint OUT "<tr><th>Version:</th><td>${BuildName} (${BuildDate})</td></tr>\n" 6127cba11262458df05951432b54997eb40a35dbf9eTed Kremenek if (defined($BuildName) && defined($BuildDate)); 6137cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 6147cba11262458df05951432b54997eb40a35dbf9eTed Kremenekprint OUT <<ENDTEXT; 6157cba11262458df05951432b54997eb40a35dbf9eTed Kremenek</table> 6166e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 6176e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 6189d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek if (scalar(@filesFound)) { 619991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Print out the summary table. 620991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my %Totals; 621ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 622991c54b9b7409656e5593364e065878b5210d556Ted Kremenek for my $row ( @Index ) { 623ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $bug_type = ($row->[2]); 624ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $bug_category = ($row->[1]); 625ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $key = "$bug_category:$bug_type"; 626ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 627ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek if (!defined $Totals{$key}) { $Totals{$key} = [1,$bug_category,$bug_type]; } 628ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek else { $Totals{$key}->[0]++; } 6296e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 630991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 6317cba11262458df05951432b54997eb40a35dbf9eTed Kremenek print OUT "<h2>Bug Summary</h2>"; 632991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 633991c54b9b7409656e5593364e065878b5210d556Ted Kremenek if (defined $BuildName) { 634991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n" 6356e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek } 636f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 6372350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek my $TotalBugs = scalar(@Index); 6386e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 639ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<table> 640ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<thead><tr><td>Bug Type</td><td>Quantity</td><td class="sorttable_nosort">Display?</td></tr></thead> 641999e120c1f5bb4064fa9961d82c2b02b6c41cb0dTed Kremenek<tr style="font-weight:bold"><td class="SUMM_DESC">All Bugs</td><td class="Q">$TotalBugs</td><td><center><input type="checkbox" id="AllBugsCheck" onClick="CopyCheckedStateToCheckButtons(this);" checked/></center></td></tr> 6426e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted KremenekENDTEXT 6436e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 644ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $last_category; 645ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 646ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek for my $key ( 647ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek sort { 648ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $x = $Totals{$a}; 649ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $y = $Totals{$b}; 650ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $res = $x->[1] cmp $y->[1]; 651ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek $res = $x->[2] cmp $y->[2] if ($res == 0); 652ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek $res 653ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek } keys %Totals ) 654ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek { 655ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $val = $Totals{$key}; 656ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $category = $val->[1]; 657ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek if (!defined $last_category or $last_category ne $category) { 658ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek $last_category = $category; 659ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "<tr><th>$category</th><th colspan=2></th></tr>\n"; 660ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek } 661ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $x = lc $key; 662ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek $x =~ s/[ ,'":\/()]+/_/g; 663ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "<tr><td class=\"SUMM_DESC\">"; 664ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT $val->[2]; 6652350a46bec7c581b2e3808e205aa3f3f5fae71ccTed Kremenek print OUT "</td><td class=\"Q\">"; 666ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT $val->[0]; 667ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "</td><td><center><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></center></td></tr>\n"; 668991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 6696e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 6706e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek # Print out the table of errors. 6716e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 6726e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenekprint OUT <<ENDTEXT; 6736e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek</table> 6747cba11262458df05951432b54997eb40a35dbf9eTed Kremenek<h2>Reports</h2> 675ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 676ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<table class="sortable" style="table-layout:automatic"> 677ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<thead><tr> 678ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek <td>Bug Group</td> 679ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek <td class="sorttable_sorted">Bug Type<span id="sorttable_sortfwdind"> ▾</span></td> 680bba1cf550015b088f94c2d3a60a769806f84cd15Ted Kremenek <td>File</td> 681ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek <td class="Q">Line</td> 68281983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek <td class="Q">Path Length</td> 6832645c77072d45fabb2bdc0a3621908035c7113dcTed Kremenek <td class="sorttable_nosort"></td> 684ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek <!-- REPORTBUGCOL --> 685ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek</tr></thead> 686ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek<tbody> 6875744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekENDTEXT 6889cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 689991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $prefix = GetPrefix(); 690991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $regex; 691991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $InFileRegex; 692991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $InFilePrefix = "File:</td><td>"; 6937a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 694991c54b9b7409656e5593364e065878b5210d556Ted Kremenek if (defined $prefix) { 695991c54b9b7409656e5593364e065878b5210d556Ted Kremenek $regex = qr/^\Q$prefix\E/is; 696991c54b9b7409656e5593364e065878b5210d556Ted Kremenek $InFileRegex = qr/\Q$InFilePrefix$prefix\E/is; 697991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 6987a4648df321be70bb009a8dc56e0162c3f13c18cTed Kremenek 699ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek for my $row ( sort { $a->[2] cmp $b->[2] } @Index ) { 700ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $x = "$row->[1]:$row->[2]"; 701ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek $x = lc $x; 702ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek $x =~ s/[ ,'":\/()]+/_/g; 7036e6eff7aaac376a08cdb3c6ae9d177491f800ca8Ted Kremenek 704991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $ReportFile = $row->[0]; 705ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 706ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "<tr class=\"bt_$x\">"; 707ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "<td class=\"DESC\">"; 708991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT $row->[1]; 709ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "</td>"; 710ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "<td class=\"DESC\">"; 711ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT $row->[2]; 712ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "</td>"; 713ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 714ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek # Update the file prefix. 715ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $fname = $row->[3]; 716ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 717991c54b9b7409656e5593364e065878b5210d556Ted Kremenek if (defined $regex) { 718991c54b9b7409656e5593364e065878b5210d556Ted Kremenek $fname =~ s/$regex//; 719991c54b9b7409656e5593364e065878b5210d556Ted Kremenek UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix) 720991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 721ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 72291639ef5aa2bd94c14ae872cf747c58174ffe9b8Ted Kremenek print OUT "<td>"; 723ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my @fname = split /\//,$fname; 724ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek if ($#fname > 0) { 725ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek while ($#fname >= 0) { 726ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek my $x = shift @fname; 727ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT $x; 728ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek if ($#fname >= 0) { 729ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "<span class=\"W\"> </span>/"; 730ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek } 731ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek } 732ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek } 733ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek else { 734ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT $fname; 73591639ef5aa2bd94c14ae872cf747c58174ffe9b8Ted Kremenek } 736ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "</td>"; 737ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 738ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek # Print out the quantities. 73981983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek for my $j ( 4 .. 5 ) { 740ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "<td class=\"Q\">$row->[$j]</td>"; 741ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek } 742ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek 743991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Print the rest of the columns. 74481983111dfa43e5f6b21b221c959586a6a766e76Ted Kremenek for (my $j = 6; $j <= $#{$row}; ++$j) { 745ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "<td>$row->[$j]</td>" 746991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 7477f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 748991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Emit the "View" link. 74968005ddb49b88c2f6cdd88185d72d8b411d2dbc9Ted Kremenek print OUT "<td><a href=\"$ReportFile#EndPath\">View Report</a></td>"; 7503cea9ee6b77ac797ebb910bdf45d1d7f8f68e37bTed Kremenek 751e43038ec3d0ef187fcdddf101ef653bbbdb1069aDaniel Dunbar # Emit REPORTBUG markers. 752ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "\n<!-- REPORTBUG id=\"$ReportFile\" -->\n"; 753e43038ec3d0ef187fcdddf101ef653bbbdb1069aDaniel Dunbar 754991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # End the row. 755991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "</tr>\n"; 756991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 757991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 758ebb7413bbe518fa6230eddebf6e51857b47b5cd3Ted Kremenek print OUT "</tbody>\n</table>\n\n"; 759991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 760991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 761938eef139ad43345248235da31f78a759dd18f13Ted Kremenek if (scalar (@failures) || scalar(@attributes_ignored)) { 762938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT "<h2>Analyzer Failures</h2>\n"; 763938eef139ad43345248235da31f78a759dd18f13Ted Kremenek 764938eef139ad43345248235da31f78a759dd18f13Ted Kremenek if (scalar @attributes_ignored) { 765938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT "The analyzer's parser ignored the following attributes:<p>\n"; 766938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT "<table>\n"; 767938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT "<thead><tr><td>Attribute</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>\n"; 768938eef139ad43345248235da31f78a759dd18f13Ted Kremenek foreach my $file (sort @attributes_ignored) { 769938eef139ad43345248235da31f78a759dd18f13Ted Kremenek die "cannot demangle attribute name\n" if (! ($file =~ /^attribute_ignored_(.+).txt/)); 770938eef139ad43345248235da31f78a759dd18f13Ted Kremenek my $attribute = $1; 771938eef139ad43345248235da31f78a759dd18f13Ted Kremenek # Open the attribute file to get the first file that failed. 772938eef139ad43345248235da31f78a759dd18f13Ted Kremenek next if (!open (ATTR, "$Dir/failures/$file")); 773938eef139ad43345248235da31f78a759dd18f13Ted Kremenek my $ppfile = <ATTR>; 774938eef139ad43345248235da31f78a759dd18f13Ted Kremenek chomp $ppfile; 775938eef139ad43345248235da31f78a759dd18f13Ted Kremenek close ATTR; 776938eef139ad43345248235da31f78a759dd18f13Ted Kremenek next if (! -e "$Dir/failures/$ppfile"); 777938eef139ad43345248235da31f78a759dd18f13Ted Kremenek # Open the info file and get the name of the source file. 778938eef139ad43345248235da31f78a759dd18f13Ted Kremenek open (INFO, "$Dir/failures/$ppfile.info.txt") or 779938eef139ad43345248235da31f78a759dd18f13Ted Kremenek die "Cannot open $Dir/failures/$ppfile.info.txt\n"; 780938eef139ad43345248235da31f78a759dd18f13Ted Kremenek my $srcfile = <INFO>; 781938eef139ad43345248235da31f78a759dd18f13Ted Kremenek chomp $srcfile; 782938eef139ad43345248235da31f78a759dd18f13Ted Kremenek close (INFO); 783938eef139ad43345248235da31f78a759dd18f13Ted Kremenek # Print the information in the table. 784938eef139ad43345248235da31f78a759dd18f13Ted Kremenek my $prefix = GetPrefix(); 785938eef139ad43345248235da31f78a759dd18f13Ted Kremenek if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; } 786938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT "<tr><td>$attribute</td><td>$srcfile</td><td><a href=\"failures/$ppfile\">$ppfile</a></td><td><a href=\"failures/$ppfile.stderr.txt\">$ppfile.stderr.txt</a></td></tr>\n"; 787938eef139ad43345248235da31f78a759dd18f13Ted Kremenek my $ppfile_clang = $ppfile; 788938eef139ad43345248235da31f78a759dd18f13Ted Kremenek $ppfile_clang =~ s/[.](.+)$/.clang.$1/; 789938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT " <!-- REPORTPROBLEM src=\"$srcfile\" file=\"failures/$ppfile\" clangfile=\"failures/$ppfile_clang\" stderr=\"failures/$ppfile.stderr.txt\" info=\"failures/$ppfile.info.txt\" -->\n"; 790938eef139ad43345248235da31f78a759dd18f13Ted Kremenek } 791938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT "</table>\n"; 792938eef139ad43345248235da31f78a759dd18f13Ted Kremenek } 793938eef139ad43345248235da31f78a759dd18f13Ted Kremenek 794938eef139ad43345248235da31f78a759dd18f13Ted Kremenek if (scalar @failures) { 795938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT "<p>The analyzer had problems processing the following files:</p>\n"; 796938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT "<table>\n"; 797938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT "<thead><tr><td>Problem</td><td>Source File</td><td>Preprocessed File</td><td>STDERR Output</td></tr></thead>\n"; 798938eef139ad43345248235da31f78a759dd18f13Ted Kremenek foreach my $file (sort @failures) { 79982a1253077cd0832e4d347062b911cd305ab62d1Ted Kremenek $file =~ /(.+).info.txt$/; 800991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Get the preprocessed file. 801991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $ppfile = $1; 802991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Open the info file and get the name of the source file. 803938eef139ad43345248235da31f78a759dd18f13Ted Kremenek open (INFO, "$Dir/failures/$file") or 804938eef139ad43345248235da31f78a759dd18f13Ted Kremenek die "Cannot open $Dir/failures/$file\n"; 805991c54b9b7409656e5593364e065878b5210d556Ted Kremenek my $srcfile = <INFO>; 8065d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek chomp $srcfile; 8075d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek my $problem = <INFO>; 8085d31f83bbe990aeb070ce6c8d919d229d4eb5052Ted Kremenek chomp $problem; 809991c54b9b7409656e5593364e065878b5210d556Ted Kremenek close (INFO); 810991c54b9b7409656e5593364e065878b5210d556Ted Kremenek # Print the information in the table. 811d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed Kremenek my $prefix = GetPrefix(); 8129f9b1fded49acff77e61b3ed1afc8bbaaefe6f34Ted Kremenek if (defined $prefix) { $srcfile =~ s/^\Q$prefix//; } 813938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT "<tr><td>$problem</td><td>$srcfile</td><td><a href=\"failures/$ppfile\">$ppfile</a></td><td><a href=\"failures/$ppfile.stderr.txt\">$ppfile.stderr.txt</a></td></tr>\n"; 814ce723ce2346fccb102d4dc93b80356824544d1afDaniel Dunbar my $ppfile_clang = $ppfile; 815ce723ce2346fccb102d4dc93b80356824544d1afDaniel Dunbar $ppfile_clang =~ s/[.](.+)$/.clang.$1/; 816938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT " <!-- REPORTPROBLEM src=\"$srcfile\" file=\"failures/$ppfile\" clangfile=\"failures/$ppfile_clang\" stderr=\"failures/$ppfile.stderr.txt\" info=\"failures/$ppfile.info.txt\" -->\n"; 817991c54b9b7409656e5593364e065878b5210d556Ted Kremenek } 818938eef139ad43345248235da31f78a759dd18f13Ted Kremenek print OUT "</table>\n"; 819938eef139ad43345248235da31f78a759dd18f13Ted Kremenek } 820e2c8663ad2b110712401145b866072bb94108058Nico Weber print OUT "<p>Please consider submitting preprocessed files as <a href=\"http://clang-analyzer.llvm.org/filing_bugs.html\">bug reports</a>. <!-- REPORTCRASHES --> </p>\n"; 8215744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek } 8225744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek 823991c54b9b7409656e5593364e065878b5210d556Ted Kremenek print OUT "</body></html>\n"; 8245744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenek close(OUT); 8253ce1207f90340f9f773ace4d475b99b75ff65088Ted Kremenek CopyFiles($Dir); 82620161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek 82720161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek # Make sure $Dir and $BaseDir are world readable/executable. 82820161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek system("chmod", "755", $Dir); 829fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $BaseDir) { system("chmod", "755", $BaseDir); } 83020161e9ed795fa7ff2f7855324aa836a927fb0f5Ted Kremenek 8314f2b10b24bab0049020d268382eda144e2aa064cTom Care # Print statistics 8324f2b10b24bab0049020d268382eda144e2aa064cTom Care print CalcStats(\@Stats) if $AnalyzerStats; 8334f2b10b24bab0049020d268382eda144e2aa064cTom Care 83423cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek my $Num = scalar(@Index); 835150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek Diag("$Num bugs found.\n"); 836150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek if ($Num > 0 && -r "$Dir/index.html") { 8375950b3f93a6e8a6ae8bd59a0ef5797e9f88f0bc3Ted Kremenek Diag("Run 'scan-view $Dir' to examine bug reports.\n"); 838150c2120ab4a44b4ac62b401ffece9049ff9b2c0Ted Kremenek } 839363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 840938eef139ad43345248235da31f78a759dd18f13Ted Kremenek DiagCrashes($Dir) if (scalar @failures || scalar @attributes_ignored); 841991c54b9b7409656e5593364e065878b5210d556Ted Kremenek 842363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek return $Num; 8439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 8449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 8459cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 846dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek# RunBuildCommand - Run the build command. 847dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 848dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 8496b6289848e215ff12d4d54fe0602d3371db52788Ted Kremeneksub AddIfNotPresent { 8506b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $Args = shift; 8516b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $Arg = shift; 8526b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek my $found = 0; 8536b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 8546b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek foreach my $k (@$Args) { 8556b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($k eq $Arg) { 8566b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek $found = 1; 8576b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek last; 8586b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 8596b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 8606b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 8616b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek if ($found == 0) { 8626b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek push @$Args, $Arg; 8636b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 8646b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek} 8656b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek 866cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremeneksub SetEnv { 867cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek my $Options = shift @_; 868cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek foreach my $opt ('CC', 'CXX', 'CLANG', 'CLANG_CXX', 869cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'CCC_ANALYZER_ANALYSIS', 'CCC_ANALYZER_PLUGINS') { 870cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek die "$opt is undefined\n" if (!defined $opt); 871cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek $ENV{$opt} = $Options->{$opt}; 872cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek } 873cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek foreach my $opt ('CCC_ANALYZER_STORE_MODEL', 874cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'CCC_ANALYZER_PLUGINS', 875cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'CCC_ANALYZER_INTERNAL_STATS', 876cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'CCC_ANALYZER_OUTPUT_FORMAT') { 877cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek my $x = $Options->{$opt}; 878cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek if (defined $x) { $ENV{$opt} = $x } 879cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek } 880cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek my $Verbose = $Options->{'VERBOSE'}; 881cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek if ($Verbose >= 2) { 882cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek $ENV{'CCC_ANALYZER_VERBOSE'} = 1; 883cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek } 884cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek if ($Verbose >= 3) { 885cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek $ENV{'CCC_ANALYZER_LOG'} = 1; 886cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek } 887cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek} 888cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 88938447a40795ef140a5d14ce43e31b60276c8d207Ted Kremeneksub RunXcodebuild { 89038447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek my $Args = shift; 89138447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek my $IgnoreErrors = shift; 89238447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek my $CCAnalyzer = shift; 89338447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek my $CXXAnalyzer = shift; 894cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek my $Options = shift; 895cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 89638447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek if ($IgnoreErrors) { 89738447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek AddIfNotPresent($Args,"-PBXBuildsContinueAfterErrors=YES"); 89838447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek } 8991afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek 9001afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek # Detect the version of Xcode. If Xcode 4.6 or higher, use new 9011afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek # in situ support for analyzer interposition without needed to override 9021afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek # the compiler. 9031afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek open(DETECT_XCODE, "xcodebuild -version |") or 9041afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek die "error: cannot detect version of xcodebuild\n"; 9051afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek 9061afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek my $oldBehavior = 1; 9071afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek 9081afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek while(<DETECT_XCODE>) { 9091afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek if (/^Xcode (.+)$/) { 910c73dcba91872322159b94dc49afb9c86d169425eTed Kremenek my $ver = $1; 911c73dcba91872322159b94dc49afb9c86d169425eTed Kremenek if ($ver =~ /^([0-9]+[.][0-9]+)[^0-9]?/) { 912c73dcba91872322159b94dc49afb9c86d169425eTed Kremenek if ($1 >= 4.6) { 913c73dcba91872322159b94dc49afb9c86d169425eTed Kremenek $oldBehavior = 0; 914c73dcba91872322159b94dc49afb9c86d169425eTed Kremenek last; 915c73dcba91872322159b94dc49afb9c86d169425eTed Kremenek } 9161afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek } 9171afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek } 9181afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek } 9191afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek close(DETECT_XCODE); 9201afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek 9211afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek if ($oldBehavior == 0) { 9221afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek my $OutputDir = $Options->{"OUTPUT_DIR"}; 9231afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek my $CLANG = $Options->{"CLANG"}; 9241afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek push @$Args, 9251afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek "RUN_CLANG_STATIC_ANALYZER=YES", 9261afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek "CLANG_ANALYZER_OUTPUT=plist-html", 9271afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek "CLANG_ANALYZER_EXEC=$CLANG", 9281afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek "CLANG_ANALYZER_OUTPUT_DIR=$OutputDir"; 9291afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek 9301afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek return (system(@$Args) >> 8); 9311afc201e644ce6379b115b1fae0608dee1b0ab5fTed Kremenek } 93238447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek 933cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek # Default to old behavior where we insert a bogus compiler. 934cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek SetEnv($Options); 935cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 93638447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek # Check if using iPhone SDK 3.0 (simulator). If so the compiler being 93738447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek # used should be gcc-4.2. 93838447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek if (!defined $ENV{"CCC_CC"}) { 93938447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek for (my $i = 0 ; $i < scalar(@$Args); ++$i) { 94038447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek if ($Args->[$i] eq "-sdk" && $i + 1 < scalar(@$Args)) { 94138447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek if (@$Args[$i+1] =~ /^iphonesimulator3/) { 94238447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek $ENV{"CCC_CC"} = "gcc-4.2"; 943cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek $ENV{"CCC_CXX"} = "g++-4.2"; 94438447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek } 94538447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek } 94638447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek } 94738447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek } 94838447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek 94938447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek # Disable PCH files until clang supports them. 95038447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek AddIfNotPresent($Args,"GCC_PRECOMPILE_PREFIX_HEADER=NO"); 95138447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek 95238447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek # When 'CC' is set, xcodebuild uses it to do all linking, even if we are 95338447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek # linking C++ object files. Set 'LDPLUSPLUS' so that xcodebuild uses 'g++' 95438447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek # (via c++-analyzer) when linking such files. 95538447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek $ENV{"LDPLUSPLUS"} = $CXXAnalyzer; 95638447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek 95738447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek return (system(@$Args) >> 8); 95838447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek} 95938447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek 960cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremeneksub RunBuildCommand { 961dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Args = shift; 9627442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek my $IgnoreErrors = shift; 963dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek my $Cmd = $Args->[0]; 9646195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek my $CCAnalyzer = shift; 965524c308506e77e173092e87a0724a27817311428Ted Kremenek my $CXXAnalyzer = shift; 966cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek my $Options = shift; 967dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 9683301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek # Get only the part of the command after the last '/'. 9693301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek if ($Cmd =~ /\/([^\/]+)$/) { 9703301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek $Cmd = $1; 9713301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek } 9723301cb103d5f32056d62f13bde036988f7cf1330Ted Kremenek 97338447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek if ($Cmd eq "xcodebuild") { 974cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek return RunXcodebuild($Args, $IgnoreErrors, $CCAnalyzer, $CXXAnalyzer, $Options); 97538447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek } 97638447a40795ef140a5d14ce43e31b60276c8d207Ted Kremenek 977cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek # Setup the environment. 978cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek SetEnv($Options); 979cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 98092548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek if ($Cmd =~ /(.*\/?gcc[^\/]*$)/ or 98192548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek $Cmd =~ /(.*\/?cc[^\/]*$)/ or 98292548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek $Cmd =~ /(.*\/?llvm-gcc[^\/]*$)/ or 98305acf8b689257d8b7349ffdfe309b4d7f7d6ae13Ted Kremenek $Cmd =~ /(.*\/?clang$)/ or 98492548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek $Cmd =~ /(.*\/?ccc-analyzer[^\/]*$)/) { 98592548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek 98692548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek if (!($Cmd =~ /ccc-analyzer/) and !defined $ENV{"CCC_CC"}) { 98751365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek $ENV{"CCC_CC"} = $1; 98892548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek } 98992548fed40519a09a1c016ceb6ab078384ab5ebcTed Kremenek 990dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek shift @$Args; 9916195c373b86963b029a2d1d2501f899789d74ba8Ted Kremenek unshift @$Args, $CCAnalyzer; 992dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek } 99351365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek elsif ($Cmd =~ /(.*\/?g\+\+[^\/]*$)/ or 99451365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek $Cmd =~ /(.*\/?c\+\+[^\/]*$)/ or 99551365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek $Cmd =~ /(.*\/?llvm-g\+\+[^\/]*$)/ or 99605acf8b689257d8b7349ffdfe309b4d7f7d6ae13Ted Kremenek $Cmd =~ /(.*\/?clang\+\+$)/ or 99751365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek $Cmd =~ /(.*\/?c\+\+-analyzer[^\/]*$)/) { 99851365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek if (!($Cmd =~ /c\+\+-analyzer/) and !defined $ENV{"CCC_CXX"}) { 99951365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek $ENV{"CCC_CXX"} = $1; 100051365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek } 100151365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek shift @$Args; 1002524c308506e77e173092e87a0724a27817311428Ted Kremenek unshift @$Args, $CXXAnalyzer; 100351365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek } 10047442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek elsif ($IgnoreErrors) { 10057442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek if ($Cmd eq "make" or $Cmd eq "gmake") { 10066fba85dc6509069ff7735283464bd02da2da6eebTed Kremenek AddIfNotPresent($Args, "CC=$CCAnalyzer"); 1007524c308506e77e173092e87a0724a27817311428Ted Kremenek AddIfNotPresent($Args, "CXX=$CXXAnalyzer"); 10086b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek AddIfNotPresent($Args,"-k"); 10098912b5427a22d9032cad959c5c22cd9d28d4a66cTed Kremenek AddIfNotPresent($Args,"-i"); 10107442ca6b274f1a935c31e34221fbd0a68077ddc5Ted Kremenek } 10116b6289848e215ff12d4d54fe0602d3371db52788Ted Kremenek } 101287752b2442260fcf569e7a1447a04cd8955494c5Ted Kremenek 10135a4ddaf39a26f9c7e30d3aeca17c702213a29d9fTed Kremenek return (system(@$Args) >> 8); 1014dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek} 1015dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek 1016dab111099e5e21b4f8eb929c7af9a7a0241eca98Ted Kremenek##----------------------------------------------------------------------------## 10179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# DisplayHelp - Utility function to display all help options. 10189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 10199cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1020a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishopsub DisplayHelp { 10219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 10225744dc294e2d658a904e6bb258c0875fbac0d4a1Ted Kremenekprint <<ENDTEXT; 1023a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam BishopUSAGE: $Prog [options] <build command> [build options] 10242b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 1025f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted KremenekENDTEXT 1026f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 1027fc1d340169265375704404a8eec1d8acf1c2038dTed Kremenek if (defined $BuildName) { 1028f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek print "ANALYZER BUILD: $BuildName ($BuildDate)\n\n"; 1029f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek } 1030f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenek 1031f4cdf41fc7a9026b24d369ba932396e7c51209b7Ted Kremenekprint <<ENDTEXT; 10322b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekOPTIONS: 10332b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 1034eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -analyze-headers 10358382cf57b722f130f1a6b45380639871c07271c1Ted Kremenek 1036eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Also analyze functions in #included files. By default, such functions 1037eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek are skipped unless they are called by functions within the main source file. 1038eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1039eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -o <output location> 1040eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1041eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Specifies the output directory for analyzer reports. Subdirectories will be 1042eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek created as needed to represent separate "runs" of the analyzer. If this 1043eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek option is not specified, a directory is created in /tmp (TMPDIR on Mac OS X) 1044eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek to store the reports. 1045eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1046eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -h 1047363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek --help 10481262fc4d66584224234691d30d779f8ff004585cTed Kremenek 1049eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Display this message. 1050eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1051eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -k 1052eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek --keep-going 1053eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1054eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Add a "keep on going" option to the specified build command. This option 1055eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek currently supports make and xcodebuild. This is a convenience option; one 1056eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek can specify this behavior directly using build options. 1057eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1058eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek --html-title [title] 1059eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek --html-title=[title] 10602b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 1061eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Specify the title used on generated HTML pages. If not specified, a default 1062eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek title will be used. 10637cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 1064eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -plist 10652c3038edc2a691b2462ef4bc7fae8f4c9a494154Anna Zaks 1066eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek By default the output of scan-build is a set of HTML files. This option 1067eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek outputs the results as a set of .plist files. 10682c3038edc2a691b2462ef4bc7fae8f4c9a494154Anna Zaks 1069eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -plist-html 1070eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1071eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek By default the output of scan-build is a set of HTML files. This option 1072eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek outputs the results as a set of HTML and .plist files. 1073eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1074eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek --status-bugs 1075eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1076eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek By default, the exit status of scan-build is the same as the executed build 1077eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek command. Specifying this option causes the exit status of scan-build to be 1 1078eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek if it found potential bugs and 0 otherwise. 1079386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek 1080eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek --use-cc [compiler path] 1081eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek --use-cc=[compiler path] 1082eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1083eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek scan-build analyzes a project by interposing a "fake compiler", which 1084eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek executes a real compiler for compilation and the static analyzer for analysis. 1085eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Because of the current implementation of interposition, scan-build does not 1086eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek know what compiler your project normally uses. Instead, it simply overrides 1087eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek the CC environment variable, and guesses your default compiler. 1088eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1089eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek In the future, this interposition mechanism to be improved, but if you need 1090eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek scan-build to use a specific compiler for *compilation* then you can use 1091eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek this option to specify a path to that compiler. 1092eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1093eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek --use-c++ [compiler path] 1094eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek --use-c++=[compiler path] 1095eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1096eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek This is the same as "-use-cc" but for C++ code. 1097eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1098eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -v 1099eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1100eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Enable verbose output from scan-build. A second and third '-v' increases 1101eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek verbosity. 1102f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek 1103eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -V 1104eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek --view 1105363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 1106eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek View analysis results in a web browser when the build completes. 11077f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 1108be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed KremenekADVANCED OPTIONS: 1109be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek 1110eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -no-failure-reports 1111eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1112eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Do not create a 'failures' subdirectory that includes analyzer crash reports 1113eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek and preprocessed source files. 1114b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 1115eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -stats 1116eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1117eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Generates visitation statistics for the project being analyzed. 11184f2b10b24bab0049020d268382eda144e2aa064cTom Care 1119eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -maxloop <loop count> 11201e548f12f7cd6631a3e688a9580ede92898d9e69Anna Zaks 1121eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Specifiy the number of times a block can be visited before giving up. 1122eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Default is 4. Increase for more comprehensive coverage at a cost of speed. 1123eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1124eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek -internal-stats 1125eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek 1126eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek Generate internal analyzer statistics. 1127810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek 11285a3581daf22f9b9d0025093b07c35a08cceeae6cTed Kremenek --use-analyzer [Xcode|path to clang] 11295a3581daf22f9b9d0025093b07c35a08cceeae6cTed Kremenek --use-analyzer=[Xcode|path to clang] 1130810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek 1131810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek scan-build uses the 'clang' executable relative to itself for static 1132810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek analysis. One can override this behavior with this option by using the 1133810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek 'clang' packaged with Xcode (on OS X) or from the PATH. 113433e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose 113533e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose --keep-empty 113633e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose 113733e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose Don't remove the build results directory even if no issues were reported. 113833e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose 113909fbf297da918760ce33302a3f709a77f43af265Ted KremenekCONTROLLING CHECKERS: 114009fbf297da918760ce33302a3f709a77f43af265Ted Kremenek 114109fbf297da918760ce33302a3f709a77f43af265Ted Kremenek A default group of checkers are always run unless explicitly disabled. 114209fbf297da918760ce33302a3f709a77f43af265Ted Kremenek Checkers may be enabled/disabled using the following options: 114309fbf297da918760ce33302a3f709a77f43af265Ted Kremenek 114409fbf297da918760ce33302a3f709a77f43af265Ted Kremenek -enable-checker [checker name] 114509fbf297da918760ce33302a3f709a77f43af265Ted Kremenek -disable-checker [checker name] 1146f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks 1147f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna ZaksLOADING CHECKERS: 1148f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks 1149f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks Loading external checkers using the clang plugin interface: 1150f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks 1151f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks -load-plugin [plugin library] 1152d52e4252264f9d1f62da0b5b89d099cd7dd7fa2fTed KremenekENDTEXT 1153b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 1154ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek# Query clang for list of checkers that are enabled. 1155f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks 1156f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks# create a list to load the plugins via the 'Xclang' command line 1157f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks# argument 1158f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaksmy @PluginLoadCommandline_xclang; 1159f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaksforeach my $param ( @PluginsToLoad ) { 1160f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks push ( @PluginLoadCommandline_xclang, "-Xclang" ); 1161f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks push ( @PluginLoadCommandline_xclang, $param ); 1162f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks} 1163ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenekmy %EnabledCheckers; 1164ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenekforeach my $lang ("c", "objective-c", "objective-c++", "c++") { 1165ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek pipe(FROM_CHILD, TO_PARENT); 1166ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek my $pid = fork(); 1167ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek if ($pid == 0) { 1168ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek close FROM_CHILD; 1169ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek open(STDOUT,">&", \*TO_PARENT); 1170ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek open(STDERR,">&", \*TO_PARENT); 1171f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks exec $Clang, ( @PluginLoadCommandline_xclang, '--analyze', '-x', $lang, '-', '-###'); 1172ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek } 1173ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek close(TO_PARENT); 1174ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek while(<FROM_CHILD>) { 1175ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek foreach my $val (split /\s+/) { 1176ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek $val =~ s/\"//g; 1177ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek if ($val =~ /-analyzer-checker\=([^\s]+)/) { 1178ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek $EnabledCheckers{$1} = 1; 1179ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek } 1180ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek } 1181ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek } 1182ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek waitpid($pid,0); 1183ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek close(FROM_CHILD); 1184ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek} 1185ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek 1186ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek# Query clang for complete list of checkers. 1187a778d710e2c62d62e0b78d120254764142801196Jordan Roseif (defined $Clang && -x $Clang) { 1188a778d710e2c62d62e0b78d120254764142801196Jordan Rose pipe(FROM_CHILD, TO_PARENT); 1189a778d710e2c62d62e0b78d120254764142801196Jordan Rose my $pid = fork(); 1190a778d710e2c62d62e0b78d120254764142801196Jordan Rose if ($pid == 0) { 1191a778d710e2c62d62e0b78d120254764142801196Jordan Rose close FROM_CHILD; 1192a778d710e2c62d62e0b78d120254764142801196Jordan Rose open(STDOUT,">&", \*TO_PARENT); 1193a778d710e2c62d62e0b78d120254764142801196Jordan Rose open(STDERR,">&", \*TO_PARENT); 1194a778d710e2c62d62e0b78d120254764142801196Jordan Rose exec $Clang, ('-cc1', @PluginsToLoad , '-analyzer-checker-help'); 1195ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek } 1196a778d710e2c62d62e0b78d120254764142801196Jordan Rose close(TO_PARENT); 1197a778d710e2c62d62e0b78d120254764142801196Jordan Rose my $foundCheckers = 0; 1198ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek while(<FROM_CHILD>) { 1199a778d710e2c62d62e0b78d120254764142801196Jordan Rose if (/CHECKERS:/) { 1200a778d710e2c62d62e0b78d120254764142801196Jordan Rose $foundCheckers = 1; 1201a778d710e2c62d62e0b78d120254764142801196Jordan Rose last; 120273078642d3c32499ee573bd458af6d384fa7f6d8Ted Kremenek } 1203a778d710e2c62d62e0b78d120254764142801196Jordan Rose } 1204a778d710e2c62d62e0b78d120254764142801196Jordan Rose if (!$foundCheckers) { 1205a778d710e2c62d62e0b78d120254764142801196Jordan Rose print " *** Could not query Clang for the list of available checkers."; 1206a778d710e2c62d62e0b78d120254764142801196Jordan Rose } 1207a778d710e2c62d62e0b78d120254764142801196Jordan Rose else { 1208a778d710e2c62d62e0b78d120254764142801196Jordan Rose print("\nAVAILABLE CHECKERS:\n\n"); 1209a778d710e2c62d62e0b78d120254764142801196Jordan Rose my $skip = 0; 1210a778d710e2c62d62e0b78d120254764142801196Jordan Rose while(<FROM_CHILD>) { 1211a778d710e2c62d62e0b78d120254764142801196Jordan Rose if (/experimental/) { 1212a778d710e2c62d62e0b78d120254764142801196Jordan Rose $skip = 1; 1213a778d710e2c62d62e0b78d120254764142801196Jordan Rose next; 1214a778d710e2c62d62e0b78d120254764142801196Jordan Rose } 1215a778d710e2c62d62e0b78d120254764142801196Jordan Rose if ($skip) { 1216a778d710e2c62d62e0b78d120254764142801196Jordan Rose next if (!/^\s\s[^\s]/); 1217a778d710e2c62d62e0b78d120254764142801196Jordan Rose $skip = 0; 1218ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek } 1219a778d710e2c62d62e0b78d120254764142801196Jordan Rose s/^\s\s//; 1220a778d710e2c62d62e0b78d120254764142801196Jordan Rose if (/^([^\s]+)/) { 1221a778d710e2c62d62e0b78d120254764142801196Jordan Rose # Is the checker enabled? 1222a778d710e2c62d62e0b78d120254764142801196Jordan Rose my $checker = $1; 1223a778d710e2c62d62e0b78d120254764142801196Jordan Rose my $enabled = 0; 1224a778d710e2c62d62e0b78d120254764142801196Jordan Rose my $aggregate = ""; 1225a778d710e2c62d62e0b78d120254764142801196Jordan Rose foreach my $domain (split /\./, $checker) { 1226a778d710e2c62d62e0b78d120254764142801196Jordan Rose $aggregate .= $domain; 1227a778d710e2c62d62e0b78d120254764142801196Jordan Rose if ($EnabledCheckers{$aggregate}) { 1228a778d710e2c62d62e0b78d120254764142801196Jordan Rose $enabled =1; 1229a778d710e2c62d62e0b78d120254764142801196Jordan Rose last; 1230a778d710e2c62d62e0b78d120254764142801196Jordan Rose } 1231a778d710e2c62d62e0b78d120254764142801196Jordan Rose # append a dot, if an additional domain is added in the next iteration 1232a778d710e2c62d62e0b78d120254764142801196Jordan Rose $aggregate .= "."; 1233a778d710e2c62d62e0b78d120254764142801196Jordan Rose } 1234ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek 1235a778d710e2c62d62e0b78d120254764142801196Jordan Rose if ($enabled) { 1236a778d710e2c62d62e0b78d120254764142801196Jordan Rose print " + "; 1237a778d710e2c62d62e0b78d120254764142801196Jordan Rose } 1238a778d710e2c62d62e0b78d120254764142801196Jordan Rose else { 1239a778d710e2c62d62e0b78d120254764142801196Jordan Rose print " "; 1240a778d710e2c62d62e0b78d120254764142801196Jordan Rose } 1241ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek } 1242ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek else { 1243ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek print " "; 1244ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek } 1245a778d710e2c62d62e0b78d120254764142801196Jordan Rose print $_; 1246ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek } 1247a778d710e2c62d62e0b78d120254764142801196Jordan Rose print "\nNOTE: \"+\" indicates that an analysis is enabled by default.\n" 1248a778d710e2c62d62e0b78d120254764142801196Jordan Rose } 1249a778d710e2c62d62e0b78d120254764142801196Jordan Rose waitpid($pid,0); 1250a778d710e2c62d62e0b78d120254764142801196Jordan Rose close(FROM_CHILD); 1251ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek} 12527fe679f300bd063d7edf7071d14c7f3823ef8cceTed Kremenek 1253b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekprint <<ENDTEXT 1254b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenek 12552b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekBUILD OPTIONS 12562b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 1257363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek You can specify any build option acceptable to the build command. 125839eefde0ae1851c8b35896ee468deb3d802d03d1Ted Kremenek 12595744dc294e2d658a904e6bb258c0875fbac0d4a1Ted KremenekEXAMPLE 12602b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 1261eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenek scan-build -o /tmp/myhtmldir make -j4 12622b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 1263eaafdfc7b475937ed194ad729407481054b99be9Ted KremenekThe above example causes analysis reports to be deposited into a subdirectory 1264eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenekof "/tmp/myhtmldir" and to run "make" with the "-j4" option. A different 1265eaafdfc7b475937ed194ad729407481054b99be9Ted Kremeneksubdirectory is created each time scan-build analyzes a project. The analyzer 1266eaafdfc7b475937ed194ad729407481054b99be9Ted Kremenekshould support most parallel builds, but not distributed builds. 12672b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek 12682b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed KremenekENDTEXT 12699cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 12709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 12719cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 12727cba11262458df05951432b54997eb40a35dbf9eTed Kremenek# HtmlEscape - HTML entity encode characters that are special in HTML 12737cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------## 12747cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 12757cba11262458df05951432b54997eb40a35dbf9eTed Kremeneksub HtmlEscape { 12767cba11262458df05951432b54997eb40a35dbf9eTed Kremenek # copy argument to new variable so we don't clobber the original 12777cba11262458df05951432b54997eb40a35dbf9eTed Kremenek my $arg = shift || ''; 12787cba11262458df05951432b54997eb40a35dbf9eTed Kremenek my $tmp = $arg; 127987f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek $tmp =~ s/&/&/g; 128087f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek $tmp =~ s/</</g; 128187f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek $tmp =~ s/>/>/g; 12827cba11262458df05951432b54997eb40a35dbf9eTed Kremenek return $tmp; 12837cba11262458df05951432b54997eb40a35dbf9eTed Kremenek} 12847cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 12857cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------## 12867cba11262458df05951432b54997eb40a35dbf9eTed Kremenek# ShellEscape - backslash escape characters that are special to the shell 12877cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------## 12887cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 12897cba11262458df05951432b54997eb40a35dbf9eTed Kremeneksub ShellEscape { 12907cba11262458df05951432b54997eb40a35dbf9eTed Kremenek # copy argument to new variable so we don't clobber the original 12917cba11262458df05951432b54997eb40a35dbf9eTed Kremenek my $arg = shift || ''; 129287f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek if ($arg =~ /["\s]/) { return "'" . $arg . "'"; } 129387f8de72a3c5d61736a14dca271504aaa5020d6fTed Kremenek return $arg; 12947cba11262458df05951432b54997eb40a35dbf9eTed Kremenek} 12957cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 12967cba11262458df05951432b54997eb40a35dbf9eTed Kremenek##----------------------------------------------------------------------------## 12979cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Process command-line arguments. 12989cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek##----------------------------------------------------------------------------## 12999cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1300e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenekmy $AnalyzeHeaders = 0; 13019cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $HtmlDir; # Parent directory to store HTML files. 13029cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekmy $IgnoreErrors = 0; # Ignore build errors. 13037f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenekmy $ViewResults = 0; # View results when the build terminates. 1304363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenekmy $ExitStatusFoundBugs = 0; # Exit status reflects whether bugs were found 130533e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rosemy $KeepEmpty = 0; # Don't remove output directory even with 0 results. 1306b7770c0b4970606b53cca14ae3ca0588a0bfcb30Ted Kremenekmy @AnalysesToRun; 130707c3767be59472e19183c7b51fae76481465cb51Zhongxing Xumy $StoreModel; 1308be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenekmy $ConstraintsModel; 13091e548f12f7cd6631a3e688a9580ede92898d9e69Anna Zaksmy $InternalStats; 13108d8bc9157fccab6a4089c41cdad9e12045edd736Ted Kremenekmy $OutputFormat = "html"; 13114f2b10b24bab0049020d268382eda144e2aa064cTom Caremy $AnalyzerStats = 0; 13124f2b10b24bab0049020d268382eda144e2aa064cTom Caremy $MaxLoop = 0; 13139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 13149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekif (!@ARGV) { 13159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek DisplayHelp(); 1316a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop exit 1; 13179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 13189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1319ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek 1320ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenekmy $displayHelp = 0; 1321810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenekmy $AnalyzerDiscoveryMethod; 1322ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek 13239cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenekwhile (@ARGV) { 13249cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 13259cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek # Scan for options we recognize. 13269cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 13279cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek my $arg = $ARGV[0]; 13289cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 13292f2418eacfdc68e09a75f4343ed93ba292e8d895Sam Bishop if ($arg eq "-h" or $arg eq "--help") { 1330ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek $displayHelp = 1; 1331ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek shift @ARGV; 1332ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek next; 13339cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 13349cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1335e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek if ($arg eq '-analyze-headers') { 1336e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek shift @ARGV; 1337e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek $AnalyzeHeaders = 1; 1338e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek next; 1339e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek } 1340e15fa2736413224dfdaf457e0fd7204d7c056b3dTed Kremenek 13419cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-o") { 13429cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 13439cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 13449cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if (!@ARGV) { 134523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("'-o' option requires a target directory name.\n"); 13469cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 13479cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1348db51a55c4922b055a90a370ce9906455887a8564Ted Kremenek # Construct an absolute path. Uses the current working directory 1349db51a55c4922b055a90a370ce9906455887a8564Ted Kremenek # as a base if the original path was not absolute. 1350db51a55c4922b055a90a370ce9906455887a8564Ted Kremenek $HtmlDir = abs_path(shift @ARGV); 1351db51a55c4922b055a90a370ce9906455887a8564Ted Kremenek 13529cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 13539cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 13547cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 13557cba11262458df05951432b54997eb40a35dbf9eTed Kremenek if ($arg =~ /^--html-title(=(.+))?$/) { 13567cba11262458df05951432b54997eb40a35dbf9eTed Kremenek shift @ARGV; 13577cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 1358278a55103a66e3a83530f15d0df3d4b80ed4cfeeTed Kremenek if (!defined $2 || $2 eq '') { 13597cba11262458df05951432b54997eb40a35dbf9eTed Kremenek if (!@ARGV) { 13607cba11262458df05951432b54997eb40a35dbf9eTed Kremenek DieDiag("'--html-title' option requires a string.\n"); 13617cba11262458df05951432b54997eb40a35dbf9eTed Kremenek } 13627cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 13637cba11262458df05951432b54997eb40a35dbf9eTed Kremenek $HtmlTitle = shift @ARGV; 13647cba11262458df05951432b54997eb40a35dbf9eTed Kremenek } else { 13657cba11262458df05951432b54997eb40a35dbf9eTed Kremenek $HtmlTitle = $2; 13667cba11262458df05951432b54997eb40a35dbf9eTed Kremenek } 13677cba11262458df05951432b54997eb40a35dbf9eTed Kremenek 13687cba11262458df05951432b54997eb40a35dbf9eTed Kremenek next; 13697cba11262458df05951432b54997eb40a35dbf9eTed Kremenek } 13709cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 13712b74ab6fdf0e3ed455bf6e0d30e24845f0c2846eTed Kremenek if ($arg eq "-k" or $arg eq "--keep-going") { 13729cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 13739cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $IgnoreErrors = 1; 13749cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 13759cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 13767fe679f300bd063d7edf7071d14c7f3823ef8cceTed Kremenek 1377f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek if ($arg =~ /^--use-cc(=(.+))?$/) { 1378f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek shift @ARGV; 1379f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek my $cc; 1380f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek 1381278a55103a66e3a83530f15d0df3d4b80ed4cfeeTed Kremenek if (!defined $2 || $2 eq "") { 1382f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek if (!@ARGV) { 1383f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek DieDiag("'--use-cc' option requires a compiler executable name.\n"); 1384f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek } 1385f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek $cc = shift @ARGV; 1386f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek } 1387f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek else { 1388f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek $cc = $2; 1389f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek } 1390f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek 1391f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek $ENV{"CCC_CC"} = $cc; 1392f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek next; 1393f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek } 1394f17ef3caf19ebff18a4ee0e7984dfc6036f34b2eTed Kremenek 13957cba11262458df05951432b54997eb40a35dbf9eTed Kremenek if ($arg =~ /^--use-c\+\+(=(.+))?$/) { 1396386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek shift @ARGV; 139751365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek my $cxx; 1398386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek 1399278a55103a66e3a83530f15d0df3d4b80ed4cfeeTed Kremenek if (!defined $2 || $2 eq "") { 1400386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek if (!@ARGV) { 1401386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek DieDiag("'--use-c++' option requires a compiler executable name.\n"); 1402386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek } 140351365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek $cxx = shift @ARGV; 1404386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek } 1405386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek else { 140651365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek $cxx = $2; 1407386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek } 140851365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek 140951365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek $ENV{"CCC_CXX"} = $cxx; 1410386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek next; 1411386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek } 1412386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek 14139cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek if ($arg eq "-v") { 14149cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek shift @ARGV; 14159cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek $Verbose++; 14169cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek next; 14179cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek } 14189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 14197f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek if ($arg eq "-V" or $arg eq "--view") { 14207f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek shift @ARGV; 14217f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek $ViewResults = 1; 14227f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek next; 14237f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek } 14247f8a32572e1ee7cf96c1a65bf0eddb0f2f9b3769Ted Kremenek 1425363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek if ($arg eq "--status-bugs") { 1426363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek shift @ARGV; 1427363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek $ExitStatusFoundBugs = 1; 1428363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek next; 1429363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek } 143007c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu 143107c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu if ($arg eq "-store") { 143207c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu shift @ARGV; 1433be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek $StoreModel = shift @ARGV; 1434be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek next; 1435be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek } 1436be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek 1437be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek if ($arg eq "-constraints") { 1438be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek shift @ARGV; 1439be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek $ConstraintsModel = shift @ARGV; 144007c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu next; 144107c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu } 14421e548f12f7cd6631a3e688a9580ede92898d9e69Anna Zaks 14431e548f12f7cd6631a3e688a9580ede92898d9e69Anna Zaks if ($arg eq "-internal-stats") { 14441e548f12f7cd6631a3e688a9580ede92898d9e69Anna Zaks shift @ARGV; 14451e548f12f7cd6631a3e688a9580ede92898d9e69Anna Zaks $InternalStats = 1; 14461e548f12f7cd6631a3e688a9580ede92898d9e69Anna Zaks next; 14471e548f12f7cd6631a3e688a9580ede92898d9e69Anna Zaks } 1448363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 1449db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek if ($arg eq "-plist") { 1450db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek shift @ARGV; 1451db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek $OutputFormat = "plist"; 1452db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek next; 1453db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek } 14547753b352366778d01c5cda4117356f181d3dd468Ted Kremenek if ($arg eq "-plist-html") { 14557753b352366778d01c5cda4117356f181d3dd468Ted Kremenek shift @ARGV; 14567753b352366778d01c5cda4117356f181d3dd468Ted Kremenek $OutputFormat = "plist-html"; 14577753b352366778d01c5cda4117356f181d3dd468Ted Kremenek next; 14587753b352366778d01c5cda4117356f181d3dd468Ted Kremenek } 1459e600bedcfea91622a0003fdb5f66c500b2f9f17dTed Kremenek 1460e600bedcfea91622a0003fdb5f66c500b2f9f17dTed Kremenek if ($arg eq "-no-failure-reports") { 1461e600bedcfea91622a0003fdb5f66c500b2f9f17dTed Kremenek $ENV{"CCC_REPORT_FAILURES"} = 0; 1462e600bedcfea91622a0003fdb5f66c500b2f9f17dTed Kremenek next; 1463e600bedcfea91622a0003fdb5f66c500b2f9f17dTed Kremenek } 14644f2b10b24bab0049020d268382eda144e2aa064cTom Care if ($arg eq "-stats") { 14654f2b10b24bab0049020d268382eda144e2aa064cTom Care shift @ARGV; 14664f2b10b24bab0049020d268382eda144e2aa064cTom Care $AnalyzerStats = 1; 14674f2b10b24bab0049020d268382eda144e2aa064cTom Care next; 14684f2b10b24bab0049020d268382eda144e2aa064cTom Care } 14694f2b10b24bab0049020d268382eda144e2aa064cTom Care if ($arg eq "-maxloop") { 14704f2b10b24bab0049020d268382eda144e2aa064cTom Care shift @ARGV; 14714f2b10b24bab0049020d268382eda144e2aa064cTom Care $MaxLoop = shift @ARGV; 14724f2b10b24bab0049020d268382eda144e2aa064cTom Care next; 14734f2b10b24bab0049020d268382eda144e2aa064cTom Care } 147409fbf297da918760ce33302a3f709a77f43af265Ted Kremenek if ($arg eq "-enable-checker") { 147509fbf297da918760ce33302a3f709a77f43af265Ted Kremenek shift @ARGV; 147609fbf297da918760ce33302a3f709a77f43af265Ted Kremenek push @AnalysesToRun, "-analyzer-checker", shift @ARGV; 147709fbf297da918760ce33302a3f709a77f43af265Ted Kremenek next; 147809fbf297da918760ce33302a3f709a77f43af265Ted Kremenek } 147909fbf297da918760ce33302a3f709a77f43af265Ted Kremenek if ($arg eq "-disable-checker") { 148009fbf297da918760ce33302a3f709a77f43af265Ted Kremenek shift @ARGV; 148109fbf297da918760ce33302a3f709a77f43af265Ted Kremenek push @AnalysesToRun, "-analyzer-disable-checker", shift @ARGV; 148209fbf297da918760ce33302a3f709a77f43af265Ted Kremenek next; 148309fbf297da918760ce33302a3f709a77f43af265Ted Kremenek } 1484f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks if ($arg eq "-load-plugin") { 1485f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks shift @ARGV; 1486f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks push @PluginsToLoad, "-load", shift @ARGV; 1487f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks next; 1488f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks } 14895a3581daf22f9b9d0025093b07c35a08cceeae6cTed Kremenek if ($arg eq "--use-analyzer") { 1490810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek shift @ARGV; 1491810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek $AnalyzerDiscoveryMethod = shift @ARGV; 1492810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek next; 1493810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek } 14945a3581daf22f9b9d0025093b07c35a08cceeae6cTed Kremenek if ($arg =~ /^--use-analyzer=(.+)$/) { 1495810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek shift @ARGV; 1496810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek $AnalyzerDiscoveryMethod = $1; 1497810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek next; 1498810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek } 149933e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose if ($arg eq "--keep-empty") { 150033e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose shift @ARGV; 150133e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose $KeepEmpty = 1; 150233e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose next; 150333e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose } 1504f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks 150523cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/); 15060062ad4f47d152def1f720878aaf5904b22aefbfTed Kremenek 15079cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek last; 15089cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek} 15099cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1510ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenekif (!@ARGV and $displayHelp == 0) { 151123cfca3760c482f8543daab62051f5eaa1f98fb4Ted Kremenek Diag("No build command specified.\n\n"); 1512ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek $displayHelp = 1; 1513ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek} 1514ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek 1515810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek# Find 'clang' 1516810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenekif (!defined $AnalyzerDiscoveryMethod) { 1517810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek $Clang = Cwd::realpath("$RealBin/bin/clang"); 1518810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek if (!defined $Clang || ! -x $Clang) { 1519810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek $Clang = Cwd::realpath("$RealBin/clang"); 1520810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek } 1521810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek if (!defined $Clang || ! -x $Clang) { 1522a778d710e2c62d62e0b78d120254764142801196Jordan Rose if (!$displayHelp) { 1523a778d710e2c62d62e0b78d120254764142801196Jordan Rose DieDiag("error: Cannot find an executable 'clang' relative to scan-build." . 1524a778d710e2c62d62e0b78d120254764142801196Jordan Rose " Consider using --use-analyzer to pick a version of 'clang' to use for static analysis.\n"); 1525a778d710e2c62d62e0b78d120254764142801196Jordan Rose } 1526810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek } 1527810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek} 1528810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenekelse { 15290d3a3fd7211a1b368d1f8c0d7ca1cfd40d31a0eaTed Kremenek if ($AnalyzerDiscoveryMethod =~ /^[Xx]code$/) { 1530810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek my $xcrun = `which xcrun`; 1531810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek chomp $xcrun; 1532810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek if ($xcrun eq "") { 1533810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek DieDiag("Cannot find 'xcrun' to find 'clang' for analysis.\n"); 1534810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek } 1535810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek $Clang = `$xcrun -toolchain XcodeDefault -find clang`; 1536810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek chomp $Clang; 1537810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek if ($Clang eq "") { 1538810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek DieDiag("No 'clang' executable found by 'xcrun'\n"); 1539810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek } 1540810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek } 1541810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek else { 1542810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek $Clang = Cwd::realpath($AnalyzerDiscoveryMethod); 15439d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek if (!defined $Clang or not -x $Clang) { 15449d9f254f7781c157256dbde4d4d961a2d89e8599Ted Kremenek DieDiag("Cannot find an executable clang at '$AnalyzerDiscoveryMethod'\n"); 1545810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek } 1546810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek } 1547810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek} 1548810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek 1549a778d710e2c62d62e0b78d120254764142801196Jordan Roseif ($displayHelp) { 1550a778d710e2c62d62e0b78d120254764142801196Jordan Rose DisplayHelp(); 1551a778d710e2c62d62e0b78d120254764142801196Jordan Rose exit 1; 1552a778d710e2c62d62e0b78d120254764142801196Jordan Rose} 1553a778d710e2c62d62e0b78d120254764142801196Jordan Rose 1554810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek$ClangCXX = $Clang; 1555810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek$ClangCXX =~ s/\-\d+\.\d+$//; 1556810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek$ClangCXX .= "++"; 155747135fe346b101c9bfb15c7309423fb57ec533f0Ted Kremenek# Make sure to use "" to handle paths with spaces. 155847135fe346b101c9bfb15c7309423fb57ec533f0Ted Kremenek$ClangVersion = HtmlEscape(`"$Clang" --version`); 1559810e6229e59796f8109e94e4a469a2dc17cf3e6dTed Kremenek 1560ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek# Determine where results go. 15617cba11262458df05951432b54997eb40a35dbf9eTed Kremenek$CmdArgs = HtmlEscape(join(' ', map(ShellEscape($_), @ARGV))); 15627cba11262458df05951432b54997eb40a35dbf9eTed Kremenek$HtmlTitle = "${CurrentDirSuffix} - scan-build results" 15637cba11262458df05951432b54997eb40a35dbf9eTed Kremenek unless (defined($HtmlTitle)); 1564386c69316668b9ea8c2591af56f994be16e3ff62Ted Kremenek 15659cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Determine the output directory for the HTML reports. 1566684bb097fbb51fe4e8852925d93d6fd2adec31c7Ted Kremenekmy $BaseDir = $HtmlDir; 1567a0e226621b424e9fcaf6bf145c6ab439fbb7b8e6Sam Bishop$HtmlDir = GetHTMLRunDir($HtmlDir); 15689cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 1569ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted Kremenek# Determine the location of ccc-analyzer. 157051365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenekmy $AbsRealBin = Cwd::realpath($RealBin); 157151365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenekmy $Cmd = "$AbsRealBin/libexec/ccc-analyzer"; 157251365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenekmy $CmdCXX = "$AbsRealBin/libexec/c++-analyzer"; 157351365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek 1574ce87b929703cac0b3f236b0b0d1c7b78d8af38f2Ted Kremenekif (!defined $Cmd || ! -x $Cmd) { 157551365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek $Cmd = "$AbsRealBin/ccc-analyzer"; 15766b89636db873142f562cf576df9bc195c5b8674bTed Kremenek DieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n") if(! -x $Cmd); 1577ce87b929703cac0b3f236b0b0d1c7b78d8af38f2Ted Kremenek} 157851365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenekif (!defined $CmdCXX || ! -x $CmdCXX) { 157951365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek $CmdCXX = "$AbsRealBin/c++-analyzer"; 158051365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek DieDiag("Executable 'c++-analyzer' does not exist at '$CmdCXX'\n") if(! -x $CmdCXX); 158151365b5f74977c13c4902991c076dff8fddc96b7Ted Kremenek} 1582f22eacb11b50e647e7d08531ca5648d3c84c38c3Ted Kremenek 1583810e6229e59796f8109e94e4a469a2dc17cf3e6dTed KremenekDiag("Using '$Clang' for static analysis\n"); 15840b6c15349121a030ce914e5192bb3621c79a0656Ted Kremenek 1585ba90e8a12e6e8889035ed57fb49b40b9cd4ef990Ted KremenekSetHtmlEnv(\@ARGV, $HtmlDir); 1586cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenekif ($AnalyzeHeaders) { push @AnalysesToRun,"-analyzer-opt-analyze-headers"; } 1587cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenekif ($AnalyzerStats) { push @AnalysesToRun, '-analyzer-checker=debug.Stats'; } 1588be92debbf1e9c38b1ae8a4a9c30377b24196ca73Ted Kremenekif ($MaxLoop > 0) { push @AnalysesToRun, "-analyzer-max-loop $MaxLoop"; } 1589cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 1590cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek# Delay setting up other environment variables in case we can do true 1591cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek# interposition. 1592cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenekmy $CCC_ANALYZER_ANALYSIS = join ' ',@AnalysesToRun; 1593cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenekmy $CCC_ANALYZER_PLUGINS = join ' ',@PluginsToLoad; 1594cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenekmy %Options = ( 1595cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'CC' => $Cmd, 1596cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'CXX' => $CmdCXX, 1597cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'CLANG' => $Clang, 1598cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'CLANG_CXX' => $ClangCXX, 1599cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'VERBOSE' => $Verbose, 1600cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'CCC_ANALYZER_ANALYSIS' => $CCC_ANALYZER_ANALYSIS, 1601cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'CCC_ANALYZER_PLUGINS' => $CCC_ANALYZER_PLUGINS, 1602cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek 'OUTPUT_DIR' => $HtmlDir 1603cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek); 1604f8e8a3eeff891d1c056c96b6d6be404533741ba7Anna Zaks 16053cab2b1c3798f2a6aa3526875801a02aebf6fc1dZhongxing Xuif (defined $StoreModel) { 1606cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek $Options{'CCC_ANALYZER_STORE_MODEL'} = $StoreModel; 160707c3767be59472e19183c7b51fae76481465cb51Zhongxing Xu} 1608be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenekif (defined $ConstraintsModel) { 1609cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek $Options{'CCC_ANALYZER_CONSTRAINTS_MODEL'} = $ConstraintsModel; 1610be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek} 16111e548f12f7cd6631a3e688a9580ede92898d9e69Anna Zaksif (defined $InternalStats) { 1612cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek $Options{'CCC_ANALYZER_INTERNAL_STATS'} = 1; 16131e548f12f7cd6631a3e688a9580ede92898d9e69Anna Zaks} 1614db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenekif (defined $OutputFormat) { 1615cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek $Options{'CCC_ANALYZER_OUTPUT_FORMAT'} = $OutputFormat; 1616db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek} 1617db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek 16189cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek# Run the build. 1619cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenekmy $ExitStatus = RunBuildCommand(\@ARGV, $IgnoreErrors, $Cmd, $CmdCXX, 1620cbea860417eea485be5bc34e6a61f267cf180a56Ted Kremenek \%Options); 16219cc8c2cc79d8c91627c0dcc5cb679aad4e37c7f5Ted Kremenek 16227753b352366778d01c5cda4117356f181d3dd468Ted Kremenekif (defined $OutputFormat) { 16231182502c78ad61693995f5b3ff516fdf983b5cd7Daniel Dunbar if ($OutputFormat =~ /plist/) { 16241182502c78ad61693995f5b3ff516fdf983b5cd7Daniel Dunbar Diag "Analysis run complete.\n"; 16251182502c78ad61693995f5b3ff516fdf983b5cd7Daniel Dunbar Diag "Analysis results (plist files) deposited in '$HtmlDir'\n"; 16261182502c78ad61693995f5b3ff516fdf983b5cd7Daniel Dunbar } 16277a334d9ed9ff7426e78a88582207b47b370ec5deTed Kremenek if ($OutputFormat =~ /html/) { 16287753b352366778d01c5cda4117356f181d3dd468Ted Kremenek # Postprocess the HTML directory. 162933e9500784a6b8dc7f01ae5c85ebf0883fbc6662Jordan Rose my $NumBugs = Postprocess($HtmlDir, $BaseDir, $AnalyzerStats, $KeepEmpty); 16307753b352366778d01c5cda4117356f181d3dd468Ted Kremenek 16317753b352366778d01c5cda4117356f181d3dd468Ted Kremenek if ($ViewResults and -r "$HtmlDir/index.html") { 16327753b352366778d01c5cda4117356f181d3dd468Ted Kremenek Diag "Analysis run complete.\n"; 16337753b352366778d01c5cda4117356f181d3dd468Ted Kremenek Diag "Viewing analysis results in '$HtmlDir' using scan-view.\n"; 16347753b352366778d01c5cda4117356f181d3dd468Ted Kremenek my $ScanView = Cwd::realpath("$RealBin/scan-view"); 16357753b352366778d01c5cda4117356f181d3dd468Ted Kremenek if (! -x $ScanView) { $ScanView = "scan-view"; } 16367753b352366778d01c5cda4117356f181d3dd468Ted Kremenek exec $ScanView, "$HtmlDir"; 16377753b352366778d01c5cda4117356f181d3dd468Ted Kremenek } 1638db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek 16397753b352366778d01c5cda4117356f181d3dd468Ted Kremenek if ($ExitStatusFoundBugs) { 16407753b352366778d01c5cda4117356f181d3dd468Ted Kremenek exit 1 if ($NumBugs > 0); 16417753b352366778d01c5cda4117356f181d3dd468Ted Kremenek exit 0; 16427753b352366778d01c5cda4117356f181d3dd468Ted Kremenek } 1643db4f5f26182c522e659af655e2582cc5ea35a971Ted Kremenek } 1644363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek} 1645363dc3f40ffc4cc71fb3a04087cf627aeb6918d4Ted Kremenek 16465656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenekexit $ExitStatus; 16475656a985574c00aa9b77fec51d41023e27e7a81fTed Kremenek 1648