aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2012-09-10 17:01:41 -0700
committerStephen Hines <srhines@google.com>2012-09-10 17:01:41 -0700
commit9f0b1324a5352713337c75ef4a5acffd96609c6c (patch)
treeb2a3d75de08ebfc054b31a420400bca7d6aaec46 /utils
parent8eba6f194484c38ed724375aeab27de556113a84 (diff)
parent654f1d508cbc9553f4931b340dfa19b453f72ebd (diff)
downloadclang-9f0b1324a5352713337c75ef4a5acffd96609c6c.tar.gz
Merge branch 'upstream' into merge-2012_09_10
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/CMakeLists.txt2
-rw-r--r--utils/TableGen/ClangCommentCommandInfoEmitter.cpp70
-rw-r--r--utils/TableGen/ClangCommentHTMLTagsEmitter.cpp69
-rw-r--r--utils/TableGen/OptParserEmitter.cpp4
-rw-r--r--utils/TableGen/TableGen.cpp24
-rw-r--r--utils/TableGen/TableGenBackends.h5
-rwxr-xr-xutils/analyzer/CmpRuns.py4
-rwxr-xr-xutils/analyzer/SATestAdd.py18
-rwxr-xr-xutils/analyzer/SATestBuild.py163
-rw-r--r--utils/analyzer/SumTimerInfo.py17
-rwxr-xr-xutils/analyzer/update_plist_test.pl51
11 files changed, 370 insertions, 57 deletions
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index 0d879214d4..d5748bc2ce 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS Support)
add_tablegen(clang-tblgen CLANG
ClangASTNodesEmitter.cpp
ClangAttrEmitter.cpp
+ ClangCommentCommandInfoEmitter.cpp
+ ClangCommentHTMLTagsEmitter.cpp
ClangDiagnosticsEmitter.cpp
ClangSACheckersEmitter.cpp
NeonEmitter.cpp
diff --git a/utils/TableGen/ClangCommentCommandInfoEmitter.cpp b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
new file mode 100644
index 0000000000..11b2f51f71
--- /dev/null
+++ b/utils/TableGen/ClangCommentCommandInfoEmitter.cpp
@@ -0,0 +1,70 @@
+//===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits command lists and efficient matchers command
+// names that are used in documentation comments.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include <vector>
+
+using namespace llvm;
+
+namespace clang {
+void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+ OS << "namespace {\n"
+ "const CommandInfo Commands[] = {\n";
+ std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Command");
+ for (size_t i = 0, e = Tags.size(); i != e; ++i) {
+ Record &Tag = *Tags[i];
+ OS << " { "
+ << "\"" << Tag.getValueAsString("Name") << "\", "
+ << "\"" << Tag.getValueAsString("EndCommandName") << "\", "
+ << i << ", "
+ << Tag.getValueAsInt("NumArgs") << ", "
+ << Tag.getValueAsBit("IsInlineCommand") << ", "
+ << Tag.getValueAsBit("IsBlockCommand") << ", "
+ << Tag.getValueAsBit("IsBriefCommand") << ", "
+ << Tag.getValueAsBit("IsReturnsCommand") << ", "
+ << Tag.getValueAsBit("IsParamCommand") << ", "
+ << Tag.getValueAsBit("IsTParamCommand") << ", "
+ << Tag.getValueAsBit("IsVerbatimBlockCommand") << ", "
+ << Tag.getValueAsBit("IsVerbatimBlockEndCommand") << ", "
+ << Tag.getValueAsBit("IsVerbatimLineCommand") << ", "
+ << Tag.getValueAsBit("IsDeclarationCommand") << ", "
+ << /* IsUnknownCommand = */ "0"
+ << " }";
+ if (i + 1 != e)
+ OS << ",";
+ OS << "\n";
+ }
+ OS << "};\n"
+ "} // unnamed namespace\n\n";
+
+ std::vector<StringMatcher::StringPair> Matches;
+ for (size_t i = 0, e = Tags.size(); i != e; ++i) {
+ Record &Tag = *Tags[i];
+ std::string Name = Tag.getValueAsString("Name");
+ std::string Return;
+ raw_string_ostream(Return) << "return &Commands[" << i << "];";
+ Matches.push_back(StringMatcher::StringPair(Name, Return));
+ }
+
+ OS << "const CommandInfo *CommandTraits::getBuiltinCommandInfo(\n"
+ << " StringRef Name) {\n";
+ StringMatcher("Name", Matches, OS).Emit();
+ OS << " return NULL;\n"
+ << "}\n\n";
+}
+} // end namespace clang
+
diff --git a/utils/TableGen/ClangCommentHTMLTagsEmitter.cpp b/utils/TableGen/ClangCommentHTMLTagsEmitter.cpp
new file mode 100644
index 0000000000..0ae23b293e
--- /dev/null
+++ b/utils/TableGen/ClangCommentHTMLTagsEmitter.cpp
@@ -0,0 +1,69 @@
+//===--- ClangCommentHTMLTagsEmitter.cpp - Generate HTML tag list for Clang -=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits efficient matchers for HTML tags that are used
+// in documentation comments.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include <vector>
+
+using namespace llvm;
+
+namespace clang {
+void EmitClangCommentHTMLTags(RecordKeeper &Records, raw_ostream &OS) {
+ std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Tag");
+ std::vector<StringMatcher::StringPair> Matches;
+ for (std::vector<Record *>::iterator I = Tags.begin(), E = Tags.end();
+ I != E; ++I) {
+ Record &Tag = **I;
+ std::string Spelling = Tag.getValueAsString("Spelling");
+ Matches.push_back(StringMatcher::StringPair(Spelling, "return true;"));
+ }
+
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+ OS << "bool isHTMLTagName(StringRef Name) {\n";
+ StringMatcher("Name", Matches, OS).Emit();
+ OS << " return false;\n"
+ << "}\n\n";
+}
+
+void EmitClangCommentHTMLTagsProperties(RecordKeeper &Records,
+ raw_ostream &OS) {
+ std::vector<Record *> Tags = Records.getAllDerivedDefinitions("Tag");
+ std::vector<StringMatcher::StringPair> MatchesEndTagOptional;
+ std::vector<StringMatcher::StringPair> MatchesEndTagForbidden;
+ for (std::vector<Record *>::iterator I = Tags.begin(), E = Tags.end();
+ I != E; ++I) {
+ Record &Tag = **I;
+ std::string Spelling = Tag.getValueAsString("Spelling");
+ StringMatcher::StringPair Match(Spelling, "return true;");
+ if (Tag.getValueAsBit("EndTagOptional"))
+ MatchesEndTagOptional.push_back(Match);
+ if (Tag.getValueAsBit("EndTagForbidden"))
+ MatchesEndTagForbidden.push_back(Match);
+ }
+
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+ OS << "bool isHTMLEndTagOptional(StringRef Name) {\n";
+ StringMatcher("Name", MatchesEndTagOptional, OS).Emit();
+ OS << " return false;\n"
+ << "}\n\n";
+
+ OS << "bool isHTMLEndTagForbidden(StringRef Name) {\n";
+ StringMatcher("Name", MatchesEndTagForbidden, OS).Emit();
+ OS << " return false;\n"
+ << "}\n\n";
+}
+} // end namespace clang
+
diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp
index b0431a9be1..c9492ad719 100644
--- a/utils/TableGen/OptParserEmitter.cpp
+++ b/utils/TableGen/OptParserEmitter.cpp
@@ -32,8 +32,8 @@ static int StrCmpOptionName(const char *A, const char *B) {
}
static int CompareOptionRecords(const void *Av, const void *Bv) {
- const Record *A = *(Record**) Av;
- const Record *B = *(Record**) Bv;
+ const Record *A = *(const Record*const*) Av;
+ const Record *B = *(const Record*const*) Bv;
// Sentinel options precede all others and are only ordered by precedence.
bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index d3408ed20f..4f7789dbef 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -42,6 +42,9 @@ enum ActionType {
GenClangDeclNodes,
GenClangStmtNodes,
GenClangSACheckers,
+ GenClangCommentHTMLTags,
+ GenClangCommentHTMLTagsProperties,
+ GenClangCommentCommandInfo,
GenOptParserDefs, GenOptParserImpl,
GenArmNeon,
GenArmNeonSema,
@@ -95,6 +98,18 @@ namespace {
"Generate Clang AST statement nodes"),
clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
"Generate Clang Static Analyzer checkers"),
+ clEnumValN(GenClangCommentHTMLTags,
+ "gen-clang-comment-html-tags",
+ "Generate efficient matchers for HTML tag "
+ "names that are used in documentation comments"),
+ clEnumValN(GenClangCommentHTMLTagsProperties,
+ "gen-clang-comment-html-tags-properties",
+ "Generate efficient matchers for HTML tag "
+ "properties"),
+ clEnumValN(GenClangCommentCommandInfo,
+ "gen-clang-comment-command-info",
+ "Generate list of commands that are used in "
+ "documentation comments"),
clEnumValN(GenArmNeon, "gen-arm-neon",
"Generate arm_neon.h for clang"),
clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
@@ -164,6 +179,15 @@ public:
case GenClangSACheckers:
EmitClangSACheckers(Records, OS);
break;
+ case GenClangCommentHTMLTags:
+ EmitClangCommentHTMLTags(Records, OS);
+ break;
+ case GenClangCommentHTMLTagsProperties:
+ EmitClangCommentHTMLTagsProperties(Records, OS);
+ break;
+ case GenClangCommentCommandInfo:
+ EmitClangCommentCommandInfo(Records, OS);
+ break;
case GenOptParserDefs:
EmitOptParser(Records, OS, true);
break;
diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
index 779de7c734..838fc84dca 100644
--- a/utils/TableGen/TableGenBackends.h
+++ b/utils/TableGen/TableGenBackends.h
@@ -47,6 +47,11 @@ void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS);
void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangCommentHTMLTags(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangCommentHTMLTagsProperties(RecordKeeper &Records, raw_ostream &OS);
+
+void EmitClangCommentCommandInfo(RecordKeeper &Records, raw_ostream &OS);
+
void EmitNeon(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS);
diff --git a/utils/analyzer/CmpRuns.py b/utils/analyzer/CmpRuns.py
index c8f05cbcf4..f2961cf0ac 100755
--- a/utils/analyzer/CmpRuns.py
+++ b/utils/analyzer/CmpRuns.py
@@ -146,9 +146,7 @@ def loadResults(path, opts, root = "", deleteEmpty=True):
for d in data['diagnostics']:
# FIXME: Why is this named files, when does it have multiple
# files?
- # TODO: Add the assert back in after we fix the
- # plist-html output.
- # assert len(d['HTMLDiagnostics_files']) == 1
+ assert len(d['HTMLDiagnostics_files']) == 1
htmlFiles.append(d.pop('HTMLDiagnostics_files')[0])
else:
htmlFiles = [None] * len(data['diagnostics'])
diff --git a/utils/analyzer/SATestAdd.py b/utils/analyzer/SATestAdd.py
index 2d32533f6b..64ff4ff656 100755
--- a/utils/analyzer/SATestAdd.py
+++ b/utils/analyzer/SATestAdd.py
@@ -33,7 +33,7 @@ def isExistingProject(PMapFile, projectID) :
# Params:
# Dir is the directory where the sources are.
# ID is a short string used to identify a project.
-def addNewProject(ID, IsScanBuild) :
+def addNewProject(ID, BuildMode) :
CurDir = os.path.abspath(os.curdir)
Dir = SATestBuild.getProjectDir(ID)
if not os.path.exists(Dir):
@@ -41,7 +41,7 @@ def addNewProject(ID, IsScanBuild) :
sys.exit(-1)
# Build the project.
- SATestBuild.testProject(ID, IsScanBuild, IsReferenceBuild=True, Dir=Dir)
+ SATestBuild.testProject(ID, BuildMode, IsReferenceBuild=True, Dir=Dir)
# Add the project ID to the project map.
ProjectMapPath = os.path.join(CurDir, SATestBuild.ProjectMapFile)
@@ -57,7 +57,7 @@ def addNewProject(ID, IsScanBuild) :
print >> sys.stdout, "Reference output has been regenerated."
else:
PMapWriter = csv.writer(PMapFile)
- PMapWriter.writerow( (ID, int(IsScanBuild)) );
+ PMapWriter.writerow( (ID, int(BuildMode)) );
print "The project map is updated: ", ProjectMapPath
finally:
PMapFile.close()
@@ -69,12 +69,14 @@ if __name__ == '__main__':
if len(sys.argv) < 2:
print >> sys.stderr, 'Usage: ', sys.argv[0],\
'project_ID <mode>' \
- 'mode - 0 for single file project; 1 for scan_build'
+ 'mode - 0 for single file project; ' \
+ '1 for scan_build; ' \
+ '2 for single file c++11 project'
sys.exit(-1)
- IsScanBuild = 1
+ BuildMode = 1
if (len(sys.argv) >= 3):
- IsScanBuild = int(sys.argv[2])
- assert((IsScanBuild == 0) | (IsScanBuild == 1))
+ BuildMode = int(sys.argv[2])
+ assert((BuildMode == 0) | (BuildMode == 1) | (BuildMode == 2))
- addNewProject(sys.argv[1], IsScanBuild)
+ addNewProject(sys.argv[1], BuildMode)
diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py
index fd4bc8a8ee..baab11312e 100755
--- a/utils/analyzer/SATestBuild.py
+++ b/utils/analyzer/SATestBuild.py
@@ -42,39 +42,66 @@ import os
import csv
import sys
import glob
+import math
import shutil
import time
import plistlib
from subprocess import check_call, CalledProcessError
-# Project map stores info about all the "registered" projects.
-ProjectMapFile = "projectMap.csv"
-
-# Names of the project specific scripts.
-# The script that needs to be executed before the build can start.
-CleanupScript = "cleanup_run_static_analyzer.sh"
-# This is a file containing commands for scan-build.
-BuildScript = "run_static_analyzer.cmd"
-
-# The log file name.
-LogFolderName = "Logs"
-BuildLogName = "run_static_analyzer.log"
-# Summary file - contains the summary of the failures. Ex: This info can be be
-# displayed when buildbot detects a build failure.
-NumOfFailuresInSummary = 10
-FailuresSummaryFileName = "failures.txt"
-# Summary of the result diffs.
-DiffsSummaryFileName = "diffs.txt"
-
-# The scan-build result directory.
-SBOutputDirName = "ScanBuildResults"
-SBOutputDirReferencePrefix = "Ref"
-
-# The list of checkers used during analyzes.
-# Currently, consists of all the non experimental checkers.
-Checkers="experimental.security.taint,core,deadcode,security,unix,osx"
-
-Verbose = 1
+#------------------------------------------------------------------------------
+# Helper functions.
+#------------------------------------------------------------------------------
+
+def detectCPUs():
+ """
+ Detects the number of CPUs on a system. Cribbed from pp.
+ """
+ # Linux, Unix and MacOS:
+ if hasattr(os, "sysconf"):
+ if os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"):
+ # Linux & Unix:
+ ncpus = os.sysconf("SC_NPROCESSORS_ONLN")
+ if isinstance(ncpus, int) and ncpus > 0:
+ return ncpus
+ else: # OSX:
+ return int(capture(['sysctl', '-n', 'hw.ncpu']))
+ # Windows:
+ if os.environ.has_key("NUMBER_OF_PROCESSORS"):
+ ncpus = int(os.environ["NUMBER_OF_PROCESSORS"])
+ if ncpus > 0:
+ return ncpus
+ return 1 # Default
+
+def which(command, paths = None):
+ """which(command, [paths]) - Look up the given command in the paths string
+ (or the PATH environment variable, if unspecified)."""
+
+ if paths is None:
+ paths = os.environ.get('PATH','')
+
+ # Check for absolute match first.
+ if os.path.exists(command):
+ return command
+
+ # Would be nice if Python had a lib function for this.
+ if not paths:
+ paths = os.defpath
+
+ # Get suffixes to search.
+ # On Cygwin, 'PATHEXT' may exist but it should not be used.
+ if os.pathsep == ';':
+ pathext = os.environ.get('PATHEXT', '').split(';')
+ else:
+ pathext = ['']
+
+ # Search the paths...
+ for path in paths.split(os.pathsep):
+ for ext in pathext:
+ p = os.path.join(path, command + ext)
+ if os.path.exists(p):
+ return p
+
+ return None
# Make sure we flush the output after every print statement.
class flushfile(object):
@@ -104,6 +131,52 @@ def getSBOutputDirName(IsReferenceBuild) :
else :
return SBOutputDirName
+#------------------------------------------------------------------------------
+# Configuration setup.
+#------------------------------------------------------------------------------
+
+# Find Clang for static analysis.
+Clang = which("clang", os.environ['PATH'])
+if not Clang:
+ print "Error: cannot find 'clang' in PATH"
+ sys.exit(-1)
+
+# Number of jobs.
+Jobs = math.ceil(detectCPUs() * 0.75)
+
+# Project map stores info about all the "registered" projects.
+ProjectMapFile = "projectMap.csv"
+
+# Names of the project specific scripts.
+# The script that needs to be executed before the build can start.
+CleanupScript = "cleanup_run_static_analyzer.sh"
+# This is a file containing commands for scan-build.
+BuildScript = "run_static_analyzer.cmd"
+
+# The log file name.
+LogFolderName = "Logs"
+BuildLogName = "run_static_analyzer.log"
+# Summary file - contains the summary of the failures. Ex: This info can be be
+# displayed when buildbot detects a build failure.
+NumOfFailuresInSummary = 10
+FailuresSummaryFileName = "failures.txt"
+# Summary of the result diffs.
+DiffsSummaryFileName = "diffs.txt"
+
+# The scan-build result directory.
+SBOutputDirName = "ScanBuildResults"
+SBOutputDirReferencePrefix = "Ref"
+
+# The list of checkers used during analyzes.
+# Currently, consists of all the non experimental checkers.
+Checkers="alpha.security.taint,core,deadcode,security,unix,osx"
+
+Verbose = 1
+
+#------------------------------------------------------------------------------
+# Test harness logic.
+#------------------------------------------------------------------------------
+
# Run pre-processing script if any.
def runCleanupScript(Dir, PBuildLogFile):
ScriptPath = os.path.join(Dir, CleanupScript)
@@ -129,13 +202,19 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
BuildScriptPath = os.path.join(Dir, BuildScript)
if not os.path.exists(BuildScriptPath):
print "Error: build script is not defined: %s" % BuildScriptPath
- sys.exit(-1)
- SBOptions = "-plist-html -o " + SBOutputDir + " "
+ sys.exit(-1)
+ SBOptions = "--use-analyzer " + Clang + " "
+ SBOptions += "-plist-html -o " + SBOutputDir + " "
SBOptions += "-enable-checker " + Checkers + " "
try:
SBCommandFile = open(BuildScriptPath, "r")
SBPrefix = "scan-build " + SBOptions + " "
for Command in SBCommandFile:
+ # If using 'make', auto imply a -jX argument
+ # to speed up analysis. xcodebuild will
+ # automatically use the maximum number of cores.
+ if Command.startswith("make "):
+ Command += "-j" + Jobs
SBCommand = SBPrefix + Command
if Verbose == 1:
print " Executing: %s" % (SBCommand,)
@@ -160,17 +239,20 @@ def isValidSingleInputFile(FileName):
(Ext == ".m") | (Ext == "")) :
return True
return False
-
+
# Run analysis on a set of preprocessed files.
-def runAnalyzePreprocessed(Dir, SBOutputDir):
+def runAnalyzePreprocessed(Dir, SBOutputDir, Mode):
if os.path.exists(os.path.join(Dir, BuildScript)):
print "Error: The preprocessed files project should not contain %s" % \
BuildScript
raise Exception()
- CmdPrefix = "clang -cc1 -analyze -analyzer-output=plist -w "
+ CmdPrefix = Clang + " -cc1 -analyze -analyzer-output=plist -w "
CmdPrefix += "-analyzer-checker=" + Checkers +" -fcxx-exceptions -fblocks "
+ if (Mode == 2) :
+ CmdPrefix += "-std=c++11 "
+
PlistPath = os.path.join(Dir, SBOutputDir, "date")
FailPath = os.path.join(PlistPath, "failures");
os.makedirs(FailPath);
@@ -208,7 +290,7 @@ def runAnalyzePreprocessed(Dir, SBOutputDir):
if Failed == False:
os.remove(LogFile.name);
-def buildProject(Dir, SBOutputDir, IsScanBuild, IsReferenceBuild):
+def buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild):
TBegin = time.time()
BuildLogPath = os.path.join(SBOutputDir, LogFolderName, BuildLogName)
@@ -238,10 +320,10 @@ def buildProject(Dir, SBOutputDir, IsScanBuild, IsReferenceBuild):
try:
runCleanupScript(Dir, PBuildLogFile)
- if IsScanBuild:
+ if (ProjectBuildMode == 1):
runScanBuild(Dir, SBOutputDir, PBuildLogFile)
else:
- runAnalyzePreprocessed(Dir, SBOutputDir)
+ runAnalyzePreprocessed(Dir, SBOutputDir, ProjectBuildMode)
if IsReferenceBuild :
runCleanupScript(Dir, PBuildLogFile)
@@ -395,7 +477,7 @@ def updateSVN(Mode, ProjectsMap):
print "Error: SVN update failed."
sys.exit(-1)
-def testProject(ID, IsScanBuild, IsReferenceBuild=False, Dir=None):
+def testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Dir=None):
print " \n\n--- Building project %s" % (ID,)
TBegin = time.time()
@@ -409,7 +491,7 @@ def testProject(ID, IsScanBuild, IsReferenceBuild=False, Dir=None):
RelOutputDir = getSBOutputDirName(IsReferenceBuild)
SBOutputDir = os.path.join(Dir, RelOutputDir)
- buildProject(Dir, SBOutputDir, IsScanBuild, IsReferenceBuild)
+ buildProject(Dir, SBOutputDir, ProjectBuildMode, IsReferenceBuild)
checkBuild(SBOutputDir)
@@ -427,8 +509,9 @@ def testAll(IsReferenceBuild = False, UpdateSVN = False):
if (len(I) != 2) :
print "Error: Rows in the ProjectMapFile should have 3 entries."
raise Exception()
- if (not ((I[1] == "1") | (I[1] == "0"))):
- print "Error: Second entry in the ProjectMapFile should be 0 or 1."
+ if (not ((I[1] == "0") | (I[1] == "1") | (I[1] == "2"))):
+ print "Error: Second entry in the ProjectMapFile should be 0" \
+ " (single file), 1 (project), or 2(single file c++11)."
raise Exception()
# When we are regenerating the reference results, we might need to
diff --git a/utils/analyzer/SumTimerInfo.py b/utils/analyzer/SumTimerInfo.py
index a6731bb8f2..4ef1ceb4ce 100644
--- a/utils/analyzer/SumTimerInfo.py
+++ b/utils/analyzer/SumTimerInfo.py
@@ -28,6 +28,8 @@ if __name__ == '__main__':
ReachableBlocks = 0
ReachedMaxSteps = 0
NumSteps = 0
+ NumInlinedCallSites = 0
+ NumBifurcatedCallSites = 0
MaxCFGSize = 0
Mode = 1
for line in f:
@@ -39,25 +41,31 @@ if __name__ == '__main__':
Count = Count + 1
if (float(s[6]) > MaxTime) :
MaxTime = float(s[6])
- if ((("warning generated." in line) or ("warnings generated." in line)) and Mode == 1) :
+ if ((("warning generated." in line) or ("warnings generated" in line)) and Mode == 1) :
s = line.split()
Warnings = Warnings + int(s[0])
- if (("The # of functions analysed (as top level)." in line) and (Mode == 1)) :
+ if (("The # of functions analysed (as top level)" in line) and (Mode == 1)) :
s = line.split()
FunctionsAnalyzed = FunctionsAnalyzed + int(s[0])
if (("The % of reachable basic blocks" in line) and (Mode == 1)) :
s = line.split()
ReachableBlocks = ReachableBlocks + int(s[0])
- if (("The # of times we reached the max number of steps." in line) and (Mode == 1)) :
+ if (("The # of times we reached the max number of steps" in line) and (Mode == 1)) :
s = line.split()
ReachedMaxSteps = ReachedMaxSteps + int(s[0])
if (("The maximum number of basic blocks in a function" in line) and (Mode == 1)) :
s = line.split()
if (MaxCFGSize < int(s[0])) :
MaxCFGSize = int(s[0])
- if (("The # of steps executed." in line) and (Mode == 1)) :
+ if (("The # of steps executed" in line) and (Mode == 1)) :
s = line.split()
NumSteps = NumSteps + int(s[0])
+ if (("The # of times we inlined a call" in line) and (Mode == 1)) :
+ s = line.split()
+ NumInlinedCallSites = NumInlinedCallSites + int(s[0])
+ if (("The # of times we split the path due to imprecise dynamic dispatch info" in line) and (Mode == 1)) :
+ s = line.split()
+ NumBifurcatedCallSites = NumBifurcatedCallSites + int(s[0])
if ((") Total" in line) and (Mode == 1)) :
s = line.split()
TotalTime = TotalTime + float(s[6])
@@ -69,6 +77,7 @@ if __name__ == '__main__':
print "Reachable Blocks %d" % (ReachableBlocks)
print "Reached Max Steps %d" % (ReachedMaxSteps)
print "Number of Steps %d" % (NumSteps)
+ print "Number of Inlined calls %d (bifurcated %d)" % (NumInlinedCallSites, NumBifurcatedCallSites)
print "MaxTime %f" % (MaxTime)
print "TotalTime %f" % (TotalTime)
print "Max CFG Size %d" % (MaxCFGSize)
diff --git a/utils/analyzer/update_plist_test.pl b/utils/analyzer/update_plist_test.pl
new file mode 100755
index 0000000000..abb74a57c3
--- /dev/null
+++ b/utils/analyzer/update_plist_test.pl
@@ -0,0 +1,51 @@
+#!/usr/bin/perl -w
+use strict;
+require File::Temp;
+use File::Temp ();
+
+die "update_plist_test <test file> <plist file>\n" if ($#ARGV < 1);
+my $testFile = shift @ARGV;
+die "error: cannot read file $testFile\n" if (! -r $testFile);
+my $plistFile = shift @ARGV;
+die "error: cannot read file $plistFile\n" if (! -r $plistFile);
+
+# Create a temp file for the new test.
+my $fh = File::Temp->new();
+my $filename = $fh->filename;
+$fh->unlink_on_destroy(1);
+
+# Copy the existing temp file, skipping the FileCheck comments.
+open (IN, $testFile) or die "cannot open $testFile\n";
+while (<IN>) {
+ next if (/^\/\/ CHECK/);
+ print $fh $_;
+}
+close(IN);
+
+# Copy the plist data, and specially format it.
+open (IN, $plistFile) or die "cannot open $plistFile\n";
+my $firstArray = 1;
+my $first = 1;
+while (<IN>) {
+ # Skip everything not indented.
+ next if (/^[^\s]/);
+ # Skip the first array entry, which is for files.
+ if ($firstArray) {
+ if (/<\/array>/) { $firstArray = 0; }
+ next;
+ }
+ # Format the CHECK lines.
+ if ($first) {
+ print $fh "// CHECK: ";
+ $first = 0;
+ }
+ else {
+ print $fh "// CHECK-NEXT: ";
+ }
+ print $fh $_;
+}
+close (IN);
+close ($fh);
+
+`cp $filename $testFile`;
+print "updated $testFile\n";