svn commit: r405902 - in head/devel/llvm37: . files

Brooks Davis brooks at FreeBSD.org
Tue Jan 12 18:57:43 UTC 2016


Author: brooks
Date: Tue Jan 12 18:57:41 2016
New Revision: 405902
URL: https://svnweb.freebsd.org/changeset/ports/405902

Log:
  Upgrade to 3.7.1 release.
  
  Bring in the clang static analyzer install bits from clang trunk.

Added:
  head/devel/llvm37/files/clang-patch-static-analizer.diff   (contents, props changed)
Modified:
  head/devel/llvm37/Makefile
  head/devel/llvm37/distinfo
  head/devel/llvm37/pkg-plist

Modified: head/devel/llvm37/Makefile
==============================================================================
--- head/devel/llvm37/Makefile	Tue Jan 12 18:22:26 2016	(r405901)
+++ head/devel/llvm37/Makefile	Tue Jan 12 18:57:41 2016	(r405902)
@@ -1,8 +1,7 @@
 # $FreeBSD$
 
 PORTNAME=	llvm
-DISTVERSION=	3.7.0
-PORTREVISION=	6
+DISTVERSION=	3.7.1
 CATEGORIES=	devel lang
 MASTER_SITES=	http://llvm.org/${PRE_}releases/${LLVM_RELEASE}/${RCDIR}
 DISTNAME=	${PORTNAME}-${DISTVERSION}.src
@@ -40,6 +39,7 @@ OPTIONS_SUB=	yes
 CLANG_DESC=	Build clang
 CLANG_EXTRA_PATCHES= \
 	${PATCHDIR}/clang-patch-fformat_extensions.diff \
+	${PATCHDIR}/clang-patch-static-analizer.diff \
 	${PATCHDIR}/clang-patch-tools_clang_lib_Headers_CMakeLists.txt \
 	${PATCHDIR}/clang-patch-tools_clang_tools_clang-format_clang-format.py \
 	${PATCHDIR}/clang-patch-svn-250416
@@ -144,8 +144,12 @@ COMMANDS+=	clang \
 		clang-check \
 		clang-cpp \
 		clang-format \
-		clang-tblgen
-MAN1SRCS+=	clang.1
+		clang-tblgen \
+		scan-build \
+		scan-view
+MAN1SRCS+=	clang.1 \
+		scan-build.1
+CLANG_PATTERN=	(c-index-test|clang|scan-|Reporter.py|ScanView.py|scanview.css|sorttable.js|startfile.py|-analyzer)
 .endif
 
 .if ${PORT_OPTIONS:MEXTRAS}
@@ -256,6 +260,21 @@ EXTRA_PATCHES+= \
 
 post-extract-CLANG-on:
 	${MV} ${WRKSRC_clang} ${PATCH_WRKSRC}/tools/clang
+	${MKDIR} ${PATCH_WRKSRC}/tools/clang/tools/scan-view/share
+	cd ${PATCH_WRKSRC}/tools/clang/tools/scan-view && \
+	    ${MV} Resources/bugcatcher.ico Resources/FileRadar.scpt \
+	    Resources/GetRadarVersion.scpt share
+	${RM} ${PATCH_WRKSRC}/tools/clang/tools/scan-build/sorttable.js
+	${RM} ${PATCH_WRKSRC}/tools/clang/tools/scan-build/scanview.css
+	${RM} ${PATCH_WRKSRC}/tools/clang/tools/scan-build/set-xcode-analyzer
+	${RM} ${PATCH_WRKSRC}/tools/clang/tools/scan-build/scan-build.1
+	${RM} ${PATCH_WRKSRC}/tools/clang/tools/scan-build/scan-build.*
+	${RM} ${PATCH_WRKSRC}/tools/clang/tools/scan-build/ccc-analyzer.*
+	${RM} ${PATCH_WRKSRC}/tools/clang/tools/scan-build/c++-analyzer.*
+	${RM} ${PATCH_WRKSRC}/tools/clang/tools/scan-view/Reporter.py
+	${RM} ${PATCH_WRKSRC}/tools/clang/tools/scan-view/ScanView.py
+	${RM} ${PATCH_WRKSRC}/tools/clang/tools/scan-view/scan-view
+	${RM} ${PATCH_WRKSRC}/tools/clang/tools/scan-view/startfile.py
 
 post-extract-EXTRAS-on:
 	${MV} ${WRKSRC_extras} ${PATCH_WRKSRC}/tools/clang/tools/extra
@@ -359,7 +378,7 @@ build-plist:
 	    ${SED} -e 's|${STAGEDIR}${PYTHON_SITELIBDIR}|%%LIT%%%%PYTHON_SITELIBDIR%%|' | \
 	    ${SORT} >> ${PLIST}.tmp
 	awk '{ \
-	    if ($$0 ~ /clang/ && $$0 !~ /(omp.h|libclang_rt|sanitizer|blacklist.txt|${EXTRAS_PATTERN})/) {printf "%%%%CLANG%%%%"} \
+	    if ($$0 ~ /${CLANG_PATTERN}/ && $$0 !~ /(omp.h|libclang_rt|sanitizer|blacklist.txt|${EXTRAS_PATTERN})/) {printf "%%%%CLANG%%%%"} \
 	    if ($$0 ~ /(sanitizer|blacklist.txt)/) {printf "%%%%COMPILER_RT%%%%"} \
 	    if ($$0 ~ /(${EXTRAS_PATTERN})/) {printf "%%%%EXTRAS%%%%"} \
 	    if ($$0 ~ /lld/ && $$0 !~ /lldb/) {printf "%%%%LLD%%%%"} \

Modified: head/devel/llvm37/distinfo
==============================================================================
--- head/devel/llvm37/distinfo	Tue Jan 12 18:22:26 2016	(r405901)
+++ head/devel/llvm37/distinfo	Tue Jan 12 18:57:41 2016	(r405902)
@@ -1,14 +1,14 @@
-SHA256 (llvm-3.7.0.src.tar.xz) = ab45895f9dcdad1e140a3a79fd709f64b05ad7364e308c0e582c5b02e9cc3153
-SIZE (llvm-3.7.0.src.tar.xz) = 14636252
-SHA256 (cfe-3.7.0.src.tar.xz) = 4ed740c5a91df1c90a4118c5154851d6a475f39a91346bdf268c1c29c13aa1cc
-SIZE (cfe-3.7.0.src.tar.xz) = 9147204
-SHA256 (clang-tools-extra-3.7.0.src.tar.xz) = 8ae8a0a3a96b7a700412d67df0af172cb2fc1326beec575fcc0f71d2e72709cd
-SIZE (clang-tools-extra-3.7.0.src.tar.xz) = 276628
-SHA256 (compiler-rt-3.7.0.src.tar.xz) = 227fa998520bc94974a428dc8e7654d9bdf277e5bc70d4064ebc05691bd62b0b
-SIZE (compiler-rt-3.7.0.src.tar.xz) = 1192832
-SHA256 (lld-3.7.0.src.tar.xz) = ddb658b789c501efbe4f54ff8ced2c07cd9ff686c92445d8a1ab2cd5dbd837ed
-SIZE (lld-3.7.0.src.tar.xz) = 586440
-SHA256 (lldb-3.7.0.src.tar.xz) = f4d7505bc111044eaa4033af012221e492938405b62522b8e3e354c20c4b71e9
-SIZE (lldb-3.7.0.src.tar.xz) = 10649660
-SHA256 (openmp-3.7.0.src.tar.xz) = 8d8a224e5689596a35652fda87e4be29853c4b85fbc7a6562019badfad779f2a
-SIZE (openmp-3.7.0.src.tar.xz) = 2251108
+SHA256 (llvm-3.7.1.src.tar.xz) = be7794ed0cec42d6c682ca8e3517535b54555a3defabec83554dbc74db545ad5
+SIZE (llvm-3.7.1.src.tar.xz) = 14592544
+SHA256 (cfe-3.7.1.src.tar.xz) = 56e2164c7c2a1772d5ed2a3e57485ff73ff06c97dff12edbeea1acc4412b0674
+SIZE (cfe-3.7.1.src.tar.xz) = 9110616
+SHA256 (compiler-rt-3.7.1.src.tar.xz) = 9d4769e4a927d3824bcb7a9c82b01e307c68588e6de4e7f04ab82d82c5af8181
+SIZE (compiler-rt-3.7.1.src.tar.xz) = 1181772
+SHA256 (clang-tools-extra-3.7.1.src.tar.xz) = 4a91edaccad1ce984c7c49a4a87db186b7f7b21267b2b03bcf4bd7820715bc6b
+SIZE (clang-tools-extra-3.7.1.src.tar.xz) = 277476
+SHA256 (lld-3.7.1.src.tar.xz) = a929cb44b45e3181a0ad02d8c9df1d3fc71e001139455c6805f3abf2835ef3ac
+SIZE (lld-3.7.1.src.tar.xz) = 586008
+SHA256 (lldb-3.7.1.src.tar.xz) = 9a0bc315ef55f44c98cdf92d064df0847f453ed156dd0ef6a87e04f5fd6a0e01
+SIZE (lldb-3.7.1.src.tar.xz) = 10650524
+SHA256 (openmp-3.7.1.src.tar.xz) = 9a702e20c247014f6de8c45b738c6ea586eca0559304520f565ac9a7cba4bf9a
+SIZE (openmp-3.7.1.src.tar.xz) = 2026988

Added: head/devel/llvm37/files/clang-patch-static-analizer.diff
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/devel/llvm37/files/clang-patch-static-analizer.diff	Tue Jan 12 18:57:41 2016	(r405902)
@@ -0,0 +1,5332 @@
+diff --git tools/clang/tools/CMakeLists.txt tools/clang/tools/CMakeLists.txt.orig
+index 891bf84..dba676a 100644
+--- tools/clang/tools/CMakeLists.txt.orig
++++ tools/clang/tools/CMakeLists.txt
+@@ -5,6 +5,8 @@ add_clang_subdirectory(driver)
+ add_subdirectory(clang-format)
+ add_subdirectory(clang-format-vs)
+ add_subdirectory(clang-fuzzer)
++add_subdirectory(scan-build)
++add_subdirectory(scan-view)
+ 
+ add_subdirectory(c-index-test)
+ add_subdirectory(libclang)
+diff --git tools/clang/tools/scan-build/CMakeLists.txt tools/clang/tools/scan-build/CMakeLists.txt.orig
+new file mode 100644
+index 0000000..78c243d
+--- /dev/null
++++ tools/clang/tools/scan-build/CMakeLists.txt
+@@ -0,0 +1,82 @@
++option(CLANG_INSTALL_SCANBUILD "Install the scan-build tool" ON)
++
++include(GNUInstallDirs)
++
++if (WIN32 AND NOT CYGWIN)
++  set(BinFiles
++        scan-build.bat)
++  set(LibexecFiles
++        ccc-analyzer.bat
++        c++-analyzer.bat)
++else()
++  set(BinFiles
++        scan-build)
++  set(LibexecFiles
++        ccc-analyzer
++        c++-analyzer)
++  if (APPLE)
++    list(APPEND BinFiles
++           set-xcode-analyzer)
++  endif()
++endif()
++
++set(ManPages
++      scan-build.1)
++
++set(ShareFiles
++      scanview.css
++      sorttable.js)
++
++
++if(CLANG_INSTALL_SCANBUILD)
++  foreach(BinFile ${BinFiles})
++    add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${BinFile}
++                       COMMAND ${CMAKE_COMMAND} -E make_directory
++                         ${CMAKE_BINARY_DIR}/bin
++                       COMMAND ${CMAKE_COMMAND} -E copy
++                         ${CMAKE_CURRENT_SOURCE_DIR}/bin/${BinFile}
++                         ${CMAKE_BINARY_DIR}/bin/
++                       DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bin/${BinFile})
++    list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${BinFile})
++    install(PROGRAMS bin/${BinFile} DESTINATION bin)
++  endforeach()
++
++  foreach(LibexecFile ${LibexecFiles})
++    add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/libexec/${LibexecFile}
++                       COMMAND ${CMAKE_COMMAND} -E make_directory
++                         ${CMAKE_BINARY_DIR}/libexec
++                       COMMAND ${CMAKE_COMMAND} -E copy
++                         ${CMAKE_CURRENT_SOURCE_DIR}/libexec/${LibexecFile}
++                         ${CMAKE_BINARY_DIR}/libexec/
++                       DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libexec/${LibexecFile})
++    list(APPEND Depends ${CMAKE_BINARY_DIR}/libexec/${LibexecFile})
++    install(PROGRAMS libexec/${LibexecFile} DESTINATION libexec)
++  endforeach()
++
++  foreach(ManPage ${ManPages})
++    add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_MANDIR}/man1/${ManPage}
++                       COMMAND ${CMAKE_COMMAND} -E make_directory
++                         ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_MANDIR}/man1
++                       COMMAND ${CMAKE_COMMAND} -E copy
++                         ${CMAKE_CURRENT_SOURCE_DIR}/man/${ManPage}
++                         ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_MANDIR}/man1/
++                       DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/man/${ManPage})
++    list(APPEND Depends ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_MANDIR}/man1/${ManPage})
++    install(PROGRAMS man/${ManPage} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
++  endforeach()
++
++  foreach(ShareFile ${ShareFiles})
++    add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/share/scan-build/${ShareFile}
++                       COMMAND ${CMAKE_COMMAND} -E make_directory
++                         ${CMAKE_BINARY_DIR}/share/scan-build
++                       COMMAND ${CMAKE_COMMAND} -E copy
++                         ${CMAKE_CURRENT_SOURCE_DIR}/share/scan-build/${ShareFile}
++                         ${CMAKE_BINARY_DIR}/share/scan-build/
++                       DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/share/scan-build/${ShareFile})
++    list(APPEND Depends ${CMAKE_BINARY_DIR}/share/scan-build/${ShareFile})
++    install(FILES share/scan-build/${ShareFile} DESTINATION share/scan-build)
++  endforeach()
++
++  add_custom_target(scan-build ALL DEPENDS ${Depends})
++  set_target_properties(scan-build PROPERTIES FOLDER "Misc")
++endif()
+diff --git tools/clang/tools/scan-build/Makefile tools/clang/tools/scan-build/Makefile.orig
+new file mode 100644
+index 0000000..23aa198
+--- /dev/null
++++ tools/clang/tools/scan-build/Makefile
+@@ -0,0 +1,53 @@
++##===- tools/scan-build/Makefile ---------------------------*- Makefile -*-===##
++# 
++#                     The LLVM Compiler Infrastructure
++#
++# This file is distributed under the University of Illinois Open Source
++# License. See LICENSE.TXT for details.
++# 
++##===----------------------------------------------------------------------===##
++
++CLANG_LEVEL := ../..
++
++include $(CLANG_LEVEL)/../../Makefile.config
++include $(CLANG_LEVEL)/Makefile
++
++ifeq ($(HOST_OS),MingW)
++  Suffix := .bat
++endif
++
++CLANG_INSTALL_SCANBUILD ?= 1
++
++ifeq ($(CLANG_INSTALL_SCANBUILD), 1)
++  InstallTargets := $(ToolDir)/scan-build$(Suffix) \
++                    $(LibexecDir)/c++-analyzer$(Suffix) \
++                    $(LibexecDir)/ccc-analyzer$(Suffix) \
++                    $(ShareDir)/scan-build/scanview.css \
++                    $(ShareDir)/scan-build/sorttable.js \
++                    $(ShareDir)/man/man1/scan-build.1
++
++  ifeq ($(HOST_OS),Darwin)
++    InstallTargets := $(InstallTargets) $(ToolDir)/set-xcode-analyzer
++  endif
++endif
++
++all:: $(InstallTargets)
++
++$(ToolDir)/%: bin/% Makefile $(ToolDir)/.dir
++	$(Echo) "Copying $(notdir $<) to the 'bin' directory..."
++	$(Verb)cp $< $@
++	$(Verb)chmod +x $@
++
++$(LibexecDir)/%: libexec/% Makefile $(LibexecDir)/.dir
++	$(Echo) "Copying $(notdir $<) to the 'libexec' directory..."
++	$(Verb)cp $< $@
++	$(Verb)chmod +x $@
++
++$(ShareDir)/man/man1/%: man/% Makefile $(ShareDir)/man/man1/.dir
++	$(Echo) "Copying $(notdir $<) to the 'man' directory..."
++	$(Verb)cp $< $@
++
++$(ShareDir)/scan-build/%: share/scan-build/% Makefile $(ShareDir)/scan-build/.dir
++	$(Echo) "Copying $(notdir $<) to the 'share' directory..."
++	$(Verb)cp $< $@
++
+diff --git tools/clang/tools/scan-build/bin/scan-build tools/clang/tools/scan-build/bin/scan-build.orig
+new file mode 100755
+index 0000000..6a14484
+--- /dev/null
++++ tools/clang/tools/scan-build/bin/scan-build
+@@ -0,0 +1,1832 @@
++#!/usr/bin/env perl
++#
++#                     The LLVM Compiler Infrastructure
++#
++# This file is distributed under the University of Illinois Open Source
++# License. See LICENSE.TXT for details.
++#
++##===----------------------------------------------------------------------===##
++#
++# A script designed to wrap a build so that all calls to gcc are intercepted
++# and piped to the static analyzer.
++#
++##===----------------------------------------------------------------------===##
++
++use strict;
++use warnings;
++use FindBin qw($RealBin);
++use Digest::MD5;
++use File::Basename;
++use File::Find;
++use File::Copy qw(copy);
++use File::Path qw( rmtree mkpath );
++use Term::ANSIColor;
++use Term::ANSIColor qw(:constants);
++use Cwd qw/ getcwd abs_path /;
++use Sys::Hostname;
++use Hash::Util qw(lock_keys);
++
++my $Prog = "scan-build";
++my $BuildName;
++my $BuildDate;
++
++my $TERM = $ENV{'TERM'};
++my $UseColor = (defined $TERM and $TERM =~ 'xterm-.*color' and -t STDOUT
++                and defined $ENV{'SCAN_BUILD_COLOR'});
++
++# Portability: getpwuid is not implemented for Win32 (see Perl language
++# reference, perlport), use getlogin instead.
++my $UserName = HtmlEscape(getlogin() || getpwuid($<) || 'unknown');
++my $HostName = HtmlEscape(hostname() || 'unknown');
++my $CurrentDir = HtmlEscape(getcwd());
++
++my $CmdArgs;
++
++my $Date = localtime();
++
++# Command-line/config arguments.
++my %Options = (
++  Verbose => 0,              # Verbose output from this script.
++  AnalyzeHeaders => 0,
++  OutputDir => undef,        # Parent directory to store HTML files.
++  HtmlTitle => basename($CurrentDir)." - scan-build results",
++  IgnoreErrors => 0,         # Ignore build errors.
++  ViewResults => 0,          # View results when the build terminates.
++  ExitStatusFoundBugs => 0,  # Exit status reflects whether bugs were found
++  KeepEmpty => 0,            # Don't remove output directory even with 0 results.
++  EnableCheckers => {},
++  DisableCheckers => {},
++  UseCC => undef,            # C compiler to use for compilation.
++  UseCXX => undef,           # C++ compiler to use for compilation.
++  AnalyzerTarget => undef,
++  StoreModel => undef,
++  ConstraintsModel => undef,
++  InternalStats => undef,
++  OutputFormat => "html",
++  ConfigOptions => [],       # Options to pass through to the analyzer's -analyzer-config flag.
++  ReportFailures => undef,
++  AnalyzerStats => 0,
++  MaxLoop => 0,
++  PluginsToLoad => [],
++  AnalyzerDiscoveryMethod => undef,
++  OverrideCompiler => 0      # The flag corresponding to the --override-compiler command line option.
++);
++lock_keys(%Options);
++
++##----------------------------------------------------------------------------##
++# Diagnostics
++##----------------------------------------------------------------------------##
++
++sub Diag {
++  if ($UseColor) {
++    print BOLD, MAGENTA "$Prog: @_";
++    print RESET;
++  }
++  else {
++    print "$Prog: @_";
++  }
++}
++
++sub ErrorDiag {
++  if ($UseColor) {
++    print STDERR BOLD, RED "$Prog: ";
++    print STDERR RESET, RED @_;
++    print STDERR RESET;
++  } else {
++    print STDERR "$Prog: @_";
++  }
++}
++
++sub DiagCrashes {
++  my $Dir = shift;
++  Diag ("The analyzer encountered problems on some source files.\n");
++  Diag ("Preprocessed versions of these sources were deposited in '$Dir/failures'.\n");
++  Diag ("Please consider submitting a bug report using these files:\n");
++  Diag ("  http://clang-analyzer.llvm.org/filing_bugs.html\n")
++}
++
++sub DieDiag {
++  if ($UseColor) {
++    print STDERR BOLD, RED "$Prog: ";
++    print STDERR RESET, RED @_;
++    print STDERR RESET;
++  }
++  else {
++    print STDERR "$Prog: ", @_;
++  }
++  exit 1;
++}
++
++##----------------------------------------------------------------------------##
++# Print default checker names
++##----------------------------------------------------------------------------##
++
++if (grep /^--help-checkers$/, @ARGV) {
++    my @options = qx($0 -h);
++    foreach (@options) {
++    next unless /^ \+/;
++    s/^\s*//;
++    my ($sign, $name, @text) = split ' ', $_;
++    print $name, $/ if $sign eq '+';
++    }
++    exit 0;
++}
++
++##----------------------------------------------------------------------------##
++# Declaration of Clang options.  Populated later.
++##----------------------------------------------------------------------------##
++
++my $Clang;
++my $ClangSB;
++my $ClangCXX;
++my $ClangVersion;
++
++##----------------------------------------------------------------------------##
++# GetHTMLRunDir - Construct an HTML directory name for the current sub-run.
++##----------------------------------------------------------------------------##
++
++sub GetHTMLRunDir {
++  die "Not enough arguments." if (@_ == 0);
++  my $Dir = shift @_;
++  my $TmpMode = 0;
++  if (!defined $Dir) {
++    $Dir = $ENV{'TMPDIR'} || $ENV{'TEMP'} || $ENV{'TMP'} || "/tmp";
++    $TmpMode = 1;
++  }
++
++  # Chop off any trailing '/' characters.
++  while ($Dir =~ /\/$/) { chop $Dir; }
++
++  # Get current date and time.
++  my @CurrentTime = localtime();
++  my $year  = $CurrentTime[5] + 1900;
++  my $day   = $CurrentTime[3];
++  my $month = $CurrentTime[4] + 1;
++  my $hour =  $CurrentTime[2];
++  my $min =   $CurrentTime[1];
++  my $sec =   $CurrentTime[0];
++
++  my $TimeString = sprintf("%02d%02d%02d", $hour, $min, $sec);
++  my $DateString = sprintf("%d-%02d-%02d-%s-$$",
++                           $year, $month, $day, $TimeString);
++
++  # Determine the run number.
++  my $RunNumber;
++
++  if (-d $Dir) {
++    if (! -r $Dir) {
++      DieDiag("directory '$Dir' exists but is not readable.\n");
++    }
++    # Iterate over all files in the specified directory.
++    my $max = 0;
++    opendir(DIR, $Dir);
++    my @FILES = grep { -d "$Dir/$_" } readdir(DIR);
++    closedir(DIR);
++
++    foreach my $f (@FILES) {
++      # Strip the prefix '$Prog-' if we are dumping files to /tmp.
++      if ($TmpMode) {
++        next if (!($f =~ /^$Prog-(.+)/));
++        $f = $1;
++      }
++
++      my @x = split/-/, $f;
++      next if (scalar(@x) != 4);
++      next if ($x[0] != $year);
++      next if ($x[1] != $month);
++      next if ($x[2] != $day);
++      next if ($x[3] != $TimeString);
++      next if ($x[4] != $$);
++
++      if ($x[5] > $max) {
++        $max = $x[5];
++      }
++    }
++
++    $RunNumber = $max + 1;
++  }
++  else {
++
++    if (-x $Dir) {
++      DieDiag("'$Dir' exists but is not a directory.\n");
++    }
++
++    if ($TmpMode) {
++      DieDiag("The directory '/tmp' does not exist or cannot be accessed.\n");
++    }
++
++    # $Dir does not exist.  It will be automatically created by the
++    # clang driver.  Set the run number to 1.
++
++    $RunNumber = 1;
++  }
++
++  die "RunNumber must be defined!" if (!defined $RunNumber);
++
++  # Append the run number.
++  my $NewDir;
++  if ($TmpMode) {
++    $NewDir = "$Dir/$Prog-$DateString-$RunNumber";
++  }
++  else {
++    $NewDir = "$Dir/$DateString-$RunNumber";
++  }
++
++  # Make sure that the directory does not exist in order to avoid hijack.
++  if (-e $NewDir) {
++      DieDiag("The directory '$NewDir' already exists.\n");
++  }
++
++  mkpath($NewDir);
++  return $NewDir;
++}
++
++sub SetHtmlEnv {
++
++  die "Wrong number of arguments." if (scalar(@_) != 2);
++
++  my $Args = shift;
++  my $Dir = shift;
++
++  die "No build command." if (scalar(@$Args) == 0);
++
++  my $Cmd = $$Args[0];
++
++  if ($Cmd =~ /configure/ || $Cmd =~ /autogen/) {
++    return;
++  }
++
++  if ($Options{Verbose}) {
++    Diag("Emitting reports for this run to '$Dir'.\n");
++  }
++
++  $ENV{'CCC_ANALYZER_HTML'} = $Dir;
++}
++
++##----------------------------------------------------------------------------##
++# ComputeDigest - Compute a digest of the specified file.
++##----------------------------------------------------------------------------##
++
++sub ComputeDigest {
++  my $FName = shift;
++  DieDiag("Cannot read $FName to compute Digest.\n") if (! -r $FName);
++
++  # Use Digest::MD5.  We don't have to be cryptographically secure.  We're
++  # just looking for duplicate files that come from a non-malicious source.
++  # We use Digest::MD5 because it is a standard Perl module that should
++  # come bundled on most systems.
++  open(FILE, $FName) or DieDiag("Cannot open $FName when computing Digest.\n");
++  binmode FILE;
++  my $Result = Digest::MD5->new->addfile(*FILE)->hexdigest;
++  close(FILE);
++
++  # Return the digest.
++  return $Result;
++}
++
++##----------------------------------------------------------------------------##
++#  UpdatePrefix - Compute the common prefix of files.
++##----------------------------------------------------------------------------##
++
++my $Prefix;
++
++sub UpdatePrefix {
++  my $x = shift;
++  my $y = basename($x);
++  $x =~ s/\Q$y\E$//;
++
++  if (!defined $Prefix) {
++    $Prefix = $x;
++    return;
++  }
++
++  chop $Prefix while (!($x =~ /^\Q$Prefix/));
++}
++
++sub GetPrefix {
++  return $Prefix;
++}
++
++##----------------------------------------------------------------------------##
++#  UpdateInFilePath - Update the path in the report file.
++##----------------------------------------------------------------------------##
++
++sub UpdateInFilePath {
++  my $fname = shift;
++  my $regex = shift;
++  my $newtext = shift;
++
++  open (RIN, $fname) or die "cannot open $fname";
++  open (ROUT, ">", "$fname.tmp") or die "cannot open $fname.tmp";
++
++  while (<RIN>) {
++    s/$regex/$newtext/;
++    print ROUT $_;
++  }
++
++  close (ROUT);
++  close (RIN);
++  rename("$fname.tmp", $fname)
++}
++
++##----------------------------------------------------------------------------##
++# AddStatLine - Decode and insert a statistics line into the database.
++##----------------------------------------------------------------------------##
++
++sub AddStatLine {
++  my $Line  = shift;
++  my $Stats = shift;
++  my $File  = shift;
++
++  print $Line . "\n";
++
++  my $Regex = qr/(.*?)\ ->\ Total\ CFGBlocks:\ (\d+)\ \|\ Unreachable
++      \ CFGBlocks:\ (\d+)\ \|\ Exhausted\ Block:\ (yes|no)\ \|\ Empty\ WorkList:
++      \ (yes|no)/x;
++
++  if ($Line !~ $Regex) {
++    return;
++  }
++
++  # Create a hash of the interesting fields
++  my $Row = {
++    Filename    => $File,
++    Function    => $1,
++    Total       => $2,
++    Unreachable => $3,
++    Aborted     => $4,
++    Empty       => $5
++  };
++
++  # Add them to the stats array
++  push @$Stats, $Row;
++}
++
++##----------------------------------------------------------------------------##
++# ScanFile - Scan a report file for various identifying attributes.
++##----------------------------------------------------------------------------##
++
++# Sometimes a source file is scanned more than once, and thus produces
++# multiple error reports.  We use a cache to solve this problem.
++
++my %AlreadyScanned;
++
++sub ScanFile {
++
++  my $Index = shift;
++  my $Dir = shift;
++  my $FName = shift;
++  my $Stats = shift;
++
++  # Compute a digest for the report file.  Determine if we have already
++  # scanned a file that looks just like it.
++
++  my $digest = ComputeDigest("$Dir/$FName");
++
++  if (defined $AlreadyScanned{$digest}) {
++    # Redundant file.  Remove it.
++    unlink("$Dir/$FName");
++    return;
++  }
++
++  $AlreadyScanned{$digest} = 1;
++
++  # At this point the report file is not world readable.  Make it happen.
++  chmod(0644, "$Dir/$FName");
++
++  # Scan the report file for tags.
++  open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n");
++
++  my $BugType        = "";
++  my $BugFile        = "";
++  my $BugFunction    = "";
++  my $BugCategory    = "";
++  my $BugDescription = "";
++  my $BugPathLength  = 1;
++  my $BugLine        = 0;
++
++  while (<IN>) {
++    last if (/<!-- BUGMETAEND -->/);
++
++    if (/<!-- BUGTYPE (.*) -->$/) {
++      $BugType = $1;
++    }
++    elsif (/<!-- BUGFILE (.*) -->$/) {
++      $BugFile = abs_path($1);
++      if (!defined $BugFile) {
++         # The file no longer exists: use the original path.
++         $BugFile = $1;
++      }
++      UpdatePrefix($BugFile);
++    }
++    elsif (/<!-- BUGPATHLENGTH (.*) -->$/) {
++      $BugPathLength = $1;
++    }
++    elsif (/<!-- BUGLINE (.*) -->$/) {
++      $BugLine = $1;
++    }
++    elsif (/<!-- BUGCATEGORY (.*) -->$/) {
++      $BugCategory = $1;
++    }
++    elsif (/<!-- BUGDESC (.*) -->$/) {
++      $BugDescription = $1;
++    }
++    elsif (/<!-- FUNCTIONNAME (.*) -->$/) {
++      $BugFunction = $1;
++    }
++
++  }
++
++
++  close(IN);
++
++  if (!defined $BugCategory) {
++    $BugCategory = "Other";
++  }
++
++  # Don't add internal statistics to the bug reports
++  if ($BugCategory =~ /statistics/i) {
++    AddStatLine($BugDescription, $Stats, $BugFile);
++    return;
++  }
++
++  push @$Index,[ $FName, $BugCategory, $BugType, $BugFile, $BugFunction, $BugLine,
++                 $BugPathLength ];
++}
++
++##----------------------------------------------------------------------------##
++# CopyFiles - Copy resource files to target directory.
++##----------------------------------------------------------------------------##
++
++sub CopyFiles {
++
++  my $Dir = shift;
++
++  my $JS = Cwd::realpath("$RealBin/../share/scan-build/sorttable.js");
++
++  DieDiag("Cannot find 'sorttable.js'.\n")
++    if (! -r $JS);
++
++  copy($JS, "$Dir");
++
++  DieDiag("Could not copy 'sorttable.js' to '$Dir'.\n")
++    if (! -r "$Dir/sorttable.js");
++
++  my $CSS = Cwd::realpath("$RealBin/../share/scan-build/scanview.css");
++
++  DieDiag("Cannot find 'scanview.css'.\n")
++    if (! -r $CSS);
++
++  copy($CSS, "$Dir");
++
++  DieDiag("Could not copy 'scanview.css' to '$Dir'.\n")
++    if (! -r $CSS);
++}
++
++##----------------------------------------------------------------------------##
++# CalcStats - Calculates visitation statistics and returns the string.
++##----------------------------------------------------------------------------##
++
++sub CalcStats {
++  my $Stats = shift;
++
++  my $TotalBlocks = 0;
++  my $UnreachedBlocks = 0;
++  my $TotalFunctions = scalar(@$Stats);
++  my $BlockAborted = 0;
++  my $WorkListAborted = 0;
++  my $Aborted = 0;
++
++  # Calculate the unique files
++  my $FilesHash = {};
++
++  foreach my $Row (@$Stats) {
++    $FilesHash->{$Row->{Filename}} = 1;
++    $TotalBlocks += $Row->{Total};
++    $UnreachedBlocks += $Row->{Unreachable};
++    $BlockAborted++ if $Row->{Aborted} eq 'yes';
++    $WorkListAborted++ if $Row->{Empty} eq 'no';
++    $Aborted++ if $Row->{Aborted} eq 'yes' || $Row->{Empty} eq 'no';
++  }
++
++  my $TotalFiles = scalar(keys(%$FilesHash));
++
++  # Calculations
++  my $PercentAborted = sprintf("%.2f", $Aborted / $TotalFunctions * 100);
++  my $PercentBlockAborted = sprintf("%.2f", $BlockAborted / $TotalFunctions
++      * 100);
++  my $PercentWorkListAborted = sprintf("%.2f", $WorkListAborted /
++      $TotalFunctions * 100);
++  my $PercentBlocksUnreached = sprintf("%.2f", $UnreachedBlocks / $TotalBlocks
++      * 100);
++
++  my $StatsString = "Analyzed $TotalBlocks blocks in $TotalFunctions functions"
++    . " in $TotalFiles files\n"
++    . "$Aborted functions aborted early ($PercentAborted%)\n"
++    . "$BlockAborted had aborted blocks ($PercentBlockAborted%)\n"
++    . "$WorkListAborted had unfinished worklists ($PercentWorkListAborted%)\n"
++    . "$UnreachedBlocks blocks were never reached ($PercentBlocksUnreached%)\n";
++
++  return $StatsString;
++}
++
++##----------------------------------------------------------------------------##
++# Postprocess - Postprocess the results of an analysis scan.
++##----------------------------------------------------------------------------##
++
++my @filesFound;
++my $baseDir;
++sub FileWanted {
++    my $baseDirRegEx = quotemeta $baseDir;
++    my $file = $File::Find::name;
++
++    # The name of the file is generated by clang binary (HTMLDiagnostics.cpp)
++    if ($file =~ /report-.*\.html$/) {
++       my $relative_file = $file;
++       $relative_file =~ s/$baseDirRegEx//g;
++       push @filesFound, $relative_file;
++    }
++}
++
++sub Postprocess {
++
++  my $Dir           = shift;
++  my $BaseDir       = shift;
++  my $AnalyzerStats = shift;
++  my $KeepEmpty     = shift;
++
++  die "No directory specified." if (!defined $Dir);
++
++  if (! -d $Dir) {
++    Diag("No bugs found.\n");
++    return 0;
++  }
++
++  $baseDir = $Dir . "/";
++  find({ wanted => \&FileWanted, follow => 0}, $Dir);
++
++  if (scalar(@filesFound) == 0 and ! -e "$Dir/failures") {
++    if (! $KeepEmpty) {
++      Diag("Removing directory '$Dir' because it contains no reports.\n");
++      rmtree($Dir) or die "Cannot rmtree '$Dir' : $!";
++    }
++    Diag("No bugs found.\n");
++    return 0;
++  }
++
++  # Scan each report file and build an index.
++  my @Index;
++  my @Stats;
++  foreach my $file (@filesFound) { ScanFile(\@Index, $Dir, $file, \@Stats); }
++
++  # Scan the failures directory and use the information in the .info files
++  # to update the common prefix directory.
++  my @failures;
++  my @attributes_ignored;
++  if (-d "$Dir/failures") {
++    opendir(DIR, "$Dir/failures");
++    @failures = grep { /[.]info.txt$/ && !/attribute_ignored/; } readdir(DIR);
++    closedir(DIR);
++    opendir(DIR, "$Dir/failures");
++    @attributes_ignored = grep { /^attribute_ignored/; } readdir(DIR);
++    closedir(DIR);
++    foreach my $file (@failures) {
++      open IN, "$Dir/failures/$file" or DieDiag("cannot open $file\n");
++      my $Path = <IN>;
++      if (defined $Path) { UpdatePrefix($Path); }
++      close IN;
++    }
++  }
++
++  # Generate an index.html file.
++  my $FName = "$Dir/index.html";
++  open(OUT, ">", $FName) or DieDiag("Cannot create file '$FName'\n");
++
++  # Print out the header.
++
++print OUT <<ENDTEXT;
++<html>
++<head>
++<title>${Options{HtmlTitle}}</title>
++<link type="text/css" rel="stylesheet" href="scanview.css"/>
++<script src="sorttable.js"></script>
++<script language='javascript' type="text/javascript">
++function SetDisplay(RowClass, DisplayVal)
++{
++  var Rows = document.getElementsByTagName("tr");
++  for ( var i = 0 ; i < Rows.length; ++i ) {
++    if (Rows[i].className == RowClass) {
++      Rows[i].style.display = DisplayVal;
++    }
++  }
++}
++
++function CopyCheckedStateToCheckButtons(SummaryCheckButton) {
++  var Inputs = document.getElementsByTagName("input");
++  for ( var i = 0 ; i < Inputs.length; ++i ) {
++    if (Inputs[i].type == "checkbox") {
++      if(Inputs[i] != SummaryCheckButton) {
++        Inputs[i].checked = SummaryCheckButton.checked;
++        Inputs[i].onclick();
++      }
++    }
++  }
++}
++
++function returnObjById( id ) {
++    if (document.getElementById)
++        var returnVar = document.getElementById(id);
++    else if (document.all)
++        var returnVar = document.all[id];
++    else if (document.layers)
++        var returnVar = document.layers[id];
++    return returnVar;
++}
++
++var NumUnchecked = 0;
++
++function ToggleDisplay(CheckButton, ClassName) {
++  if (CheckButton.checked) {
++    SetDisplay(ClassName, "");
++    if (--NumUnchecked == 0) {
++      returnObjById("AllBugsCheck").checked = true;
++    }
++  }
++  else {
++    SetDisplay(ClassName, "none");
++    NumUnchecked++;
++    returnObjById("AllBugsCheck").checked = false;
++  }
++}
++</script>
++<!-- SUMMARYENDHEAD -->
++</head>
++<body>
++<h1>${Options{HtmlTitle}}</h1>
++
++<table>
++<tr><th>User:</th><td>${UserName}\@${HostName}</td></tr>
++<tr><th>Working Directory:</th><td>${CurrentDir}</td></tr>
++<tr><th>Command Line:</th><td>${CmdArgs}</td></tr>
++<tr><th>Clang Version:</th><td>${ClangVersion}</td></tr>
++<tr><th>Date:</th><td>${Date}</td></tr>
++ENDTEXT
++
++print OUT "<tr><th>Version:</th><td>${BuildName} (${BuildDate})</td></tr>\n"
++  if (defined($BuildName) && defined($BuildDate));
++
++print OUT <<ENDTEXT;
++</table>
++ENDTEXT
++
++  if (scalar(@filesFound)) {
++    # Print out the summary table.
++    my %Totals;
++
++    for my $row ( @Index ) {
++      my $bug_type = ($row->[2]);
++      my $bug_category = ($row->[1]);
++      my $key = "$bug_category:$bug_type";
++
++      if (!defined $Totals{$key}) { $Totals{$key} = [1,$bug_category,$bug_type]; }
++      else { $Totals{$key}->[0]++; }
++    }
++
++    print OUT "<h2>Bug Summary</h2>";
++
++    if (defined $BuildName) {
++      print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n"
++    }
++
++  my $TotalBugs = scalar(@Index);
++print OUT <<ENDTEXT;
++<table>
++<thead><tr><td>Bug Type</td><td>Quantity</td><td class="sorttable_nosort">Display?</td></tr></thead>
++<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>
++ENDTEXT
++
++    my $last_category;
++
++    for my $key (
++      sort {
++        my $x = $Totals{$a};
++        my $y = $Totals{$b};
++        my $res = $x->[1] cmp $y->[1];
++        $res = $x->[2] cmp $y->[2] if ($res == 0);
++        $res
++      } keys %Totals )
++    {
++      my $val = $Totals{$key};
++      my $category = $val->[1];
++      if (!defined $last_category or $last_category ne $category) {
++        $last_category = $category;
++        print OUT "<tr><th>$category</th><th colspan=2></th></tr>\n";
++      }
++      my $x = lc $key;
++      $x =~ s/[ ,'":\/()]+/_/g;
++      print OUT "<tr><td class=\"SUMM_DESC\">";
++      print OUT $val->[2];
++      print OUT "</td><td class=\"Q\">";
++      print OUT $val->[0];
++      print OUT "</td><td><center><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></center></td></tr>\n";
++    }
++
++  # Print out the table of errors.

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-ports-head mailing list