aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2012-04-14 14:01:31 +0000
committerDimitry Andric <dim@FreeBSD.org>2012-04-14 14:01:31 +0000
commitdbe13110f59f48b4dbb7552b3ac2935acdeece7f (patch)
treebe1815eb79b42ff482a8562b13c2dcbf0c5dcbee /utils
parent9da628931ebf2609493570f87824ca22402cc65f (diff)
Notes
Diffstat (limited to 'utils')
-rw-r--r--utils/C++Tests/LLVM-Code-Compile/lit.local.cfg8
-rw-r--r--utils/C++Tests/LLVM-Code-Symbols/lit.local.cfg8
-rw-r--r--utils/C++Tests/LLVM-Code-Syntax/lit.local.cfg8
-rwxr-xr-xutils/FuzzTest18
-rw-r--r--utils/TableGen/CMakeLists.txt1
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp318
-rw-r--r--utils/TableGen/ClangAttrEmitter.h39
-rw-r--r--utils/TableGen/ClangDiagnosticsEmitter.cpp113
-rw-r--r--utils/TableGen/NeonEmitter.cpp91
-rw-r--r--utils/TableGen/NeonEmitter.h34
-rw-r--r--utils/TableGen/TableGen.cpp26
-rwxr-xr-xutils/analyzer/CmpRuns.py33
-rw-r--r--utils/analyzer/SATestAdd.py41
-rw-r--r--utils/analyzer/SATestBuild.py262
-rw-r--r--utils/clangVisualizers.txt92
-rw-r--r--utils/find-unused-diagnostics.sh19
16 files changed, 908 insertions, 203 deletions
diff --git a/utils/C++Tests/LLVM-Code-Compile/lit.local.cfg b/utils/C++Tests/LLVM-Code-Compile/lit.local.cfg
index 6676e311e3ec..c1ac6a9a1f59 100644
--- a/utils/C++Tests/LLVM-Code-Compile/lit.local.cfg
+++ b/utils/C++Tests/LLVM-Code-Compile/lit.local.cfg
@@ -16,10 +16,7 @@ cxxflags = ['-D__STDC_LIMIT_MACROS',
'-Wno-sign-compare',
'-I%s/include' % root.llvm_src_root,
'-I%s/include' % root.llvm_obj_root,
- '-I%s/lib/Target/Alpha' % root.llvm_src_root,
'-I%s/lib/Target/ARM' % root.llvm_src_root,
- '-I%s/lib/Target/Blackfin' % root.llvm_src_root,
- '-I%s/lib/Target/CBackend' % root.llvm_src_root,
'-I%s/lib/Target/CellSPU' % root.llvm_src_root,
'-I%s/lib/Target/CppBackend' % root.llvm_src_root,
'-I%s/lib/Target/Mips' % root.llvm_src_root,
@@ -28,13 +25,9 @@ cxxflags = ['-D__STDC_LIMIT_MACROS',
'-I%s/lib/Target/PIC16' % root.llvm_src_root,
'-I%s/lib/Target/PowerPC' % root.llvm_src_root,
'-I%s/lib/Target/Sparc' % root.llvm_src_root,
- '-I%s/lib/Target/SystemZ' % root.llvm_src_root,
'-I%s/lib/Target/X86' % root.llvm_src_root,
'-I%s/lib/Target/XCore' % root.llvm_src_root,
- '-I%s/lib/Target/Alpha' % target_obj_root,
'-I%s/lib/Target/ARM' % target_obj_root,
- '-I%s/lib/Target/Blackfin' % target_obj_root,
- '-I%s/lib/Target/CBackend' % target_obj_root,
'-I%s/lib/Target/CellSPU' % target_obj_root,
'-I%s/lib/Target/CppBackend' % target_obj_root,
'-I%s/lib/Target/Mips' % target_obj_root,
@@ -43,7 +36,6 @@ cxxflags = ['-D__STDC_LIMIT_MACROS',
'-I%s/lib/Target/PIC16' % target_obj_root,
'-I%s/lib/Target/PowerPC' % target_obj_root,
'-I%s/lib/Target/Sparc' % target_obj_root,
- '-I%s/lib/Target/SystemZ' % target_obj_root,
'-I%s/lib/Target/X86' % target_obj_root,
'-I%s/lib/Target/XCore' % target_obj_root];
diff --git a/utils/C++Tests/LLVM-Code-Symbols/lit.local.cfg b/utils/C++Tests/LLVM-Code-Symbols/lit.local.cfg
index c328a25127d9..7882813d79c6 100644
--- a/utils/C++Tests/LLVM-Code-Symbols/lit.local.cfg
+++ b/utils/C++Tests/LLVM-Code-Symbols/lit.local.cfg
@@ -16,10 +16,7 @@ cxxflags = ['-D__STDC_LIMIT_MACROS',
'-Wno-sign-compare',
'-I%s/include' % root.llvm_src_root,
'-I%s/include' % root.llvm_obj_root,
- '-I%s/lib/Target/Alpha' % root.llvm_src_root,
'-I%s/lib/Target/ARM' % root.llvm_src_root,
- '-I%s/lib/Target/Blackfin' % root.llvm_src_root,
- '-I%s/lib/Target/CBackend' % root.llvm_src_root,
'-I%s/lib/Target/CellSPU' % root.llvm_src_root,
'-I%s/lib/Target/CppBackend' % root.llvm_src_root,
'-I%s/lib/Target/Mips' % root.llvm_src_root,
@@ -28,13 +25,9 @@ cxxflags = ['-D__STDC_LIMIT_MACROS',
'-I%s/lib/Target/PIC16' % root.llvm_src_root,
'-I%s/lib/Target/PowerPC' % root.llvm_src_root,
'-I%s/lib/Target/Sparc' % root.llvm_src_root,
- '-I%s/lib/Target/SystemZ' % root.llvm_src_root,
'-I%s/lib/Target/X86' % root.llvm_src_root,
'-I%s/lib/Target/XCore' % root.llvm_src_root,
- '-I%s/lib/Target/Alpha' % target_obj_root,
'-I%s/lib/Target/ARM' % target_obj_root,
- '-I%s/lib/Target/Blackfin' % target_obj_root,
- '-I%s/lib/Target/CBackend' % target_obj_root,
'-I%s/lib/Target/CellSPU' % target_obj_root,
'-I%s/lib/Target/CppBackend' % target_obj_root,
'-I%s/lib/Target/Mips' % target_obj_root,
@@ -43,7 +36,6 @@ cxxflags = ['-D__STDC_LIMIT_MACROS',
'-I%s/lib/Target/PIC16' % target_obj_root,
'-I%s/lib/Target/PowerPC' % target_obj_root,
'-I%s/lib/Target/Sparc' % target_obj_root,
- '-I%s/lib/Target/SystemZ' % target_obj_root,
'-I%s/lib/Target/X86' % target_obj_root,
'-I%s/lib/Target/XCore' % target_obj_root];
diff --git a/utils/C++Tests/LLVM-Code-Syntax/lit.local.cfg b/utils/C++Tests/LLVM-Code-Syntax/lit.local.cfg
index 6e679659c44c..42bec2d767a8 100644
--- a/utils/C++Tests/LLVM-Code-Syntax/lit.local.cfg
+++ b/utils/C++Tests/LLVM-Code-Syntax/lit.local.cfg
@@ -15,10 +15,7 @@ cxxflags = ['-D__STDC_LIMIT_MACROS',
'-D__STDC_CONSTANT_MACROS',
'-I%s/include' % root.llvm_src_root,
'-I%s/include' % root.llvm_obj_root,
- '-I%s/lib/Target/Alpha' % root.llvm_src_root,
'-I%s/lib/Target/ARM' % root.llvm_src_root,
- '-I%s/lib/Target/Blackfin' % root.llvm_src_root,
- '-I%s/lib/Target/CBackend' % root.llvm_src_root,
'-I%s/lib/Target/CellSPU' % root.llvm_src_root,
'-I%s/lib/Target/CppBackend' % root.llvm_src_root,
'-I%s/lib/Target/Mips' % root.llvm_src_root,
@@ -27,13 +24,9 @@ cxxflags = ['-D__STDC_LIMIT_MACROS',
'-I%s/lib/Target/PIC16' % root.llvm_src_root,
'-I%s/lib/Target/PowerPC' % root.llvm_src_root,
'-I%s/lib/Target/Sparc' % root.llvm_src_root,
- '-I%s/lib/Target/SystemZ' % root.llvm_src_root,
'-I%s/lib/Target/X86' % root.llvm_src_root,
'-I%s/lib/Target/XCore' % root.llvm_src_root,
- '-I%s/lib/Target/Alpha' % target_obj_root,
'-I%s/lib/Target/ARM' % target_obj_root,
- '-I%s/lib/Target/Blackfin' % target_obj_root,
- '-I%s/lib/Target/CBackend' % target_obj_root,
'-I%s/lib/Target/CellSPU' % target_obj_root,
'-I%s/lib/Target/CppBackend' % target_obj_root,
'-I%s/lib/Target/Mips' % target_obj_root,
@@ -42,7 +35,6 @@ cxxflags = ['-D__STDC_LIMIT_MACROS',
'-I%s/lib/Target/PIC16' % target_obj_root,
'-I%s/lib/Target/PowerPC' % target_obj_root,
'-I%s/lib/Target/Sparc' % target_obj_root,
- '-I%s/lib/Target/SystemZ' % target_obj_root,
'-I%s/lib/Target/X86' % target_obj_root,
'-I%s/lib/Target/XCore' % target_obj_root];
diff --git a/utils/FuzzTest b/utils/FuzzTest
index 2aa5989a80d4..0e043df7cf08 100755
--- a/utils/FuzzTest
+++ b/utils/FuzzTest
@@ -156,6 +156,7 @@ def run_one_test(test_application, index, input_files, args):
print 'FAIL: %d' % index
elif not opts.succinct:
print 'PASS: %d' % index
+ return test_result
def main():
global opts
@@ -182,7 +183,7 @@ test and then leave the fuzzed inputs in place to examine the failure.
For each fuzzed input, %prog will run the test command given on the command
line. Each argument in the command is subject to string interpolation before
being executed. The syntax is "%(VARIABLE)FORMAT" where FORMAT is a standard
-printf format, and VARIBLE is one of:
+printf format, and VARIABLE is one of:
'index' - the test index being run
'inputs' - the full list of test inputs
@@ -194,6 +195,10 @@ printf format, and VARIBLE is one of:
By default, the script will run forever continually picking new tests to
run. You can limit the number of tests that are run with '--max-tests <number>',
and you can run a particular test with '--test <index>'.
+
+You can specify '--stop-on-fail' to stop the script on the first failure
+without reverting the changes.
+
""")
parser.add_option("-v", "--verbose", help="Show more output",
action='store_true', dest="verbose", default=False)
@@ -223,7 +228,7 @@ and you can run a particular test with '--test <index>'.
type=str, action="append", dest="input_files", default=[])
group.add_option("", "--filelist", metavar="LIST",
help="Add a list of inputs files to fuzz (one per line)",
- type=int, action="append", dest="filelists", default=[])
+ type=str, action="append", dest="filelists", default=[])
parser.add_option_group(group)
group = OptionGroup(parser, "Fuzz Options")
@@ -244,13 +249,15 @@ and you can run a particular test with '--test <index>'.
action='store_false', dest="enable_replace", default=True)
group.add_option("", "--no-revert", help="Don't revert changes",
action='store_false', dest="revert", default=True)
+ group.add_option("", "--stop-on-fail", help="Stop on first failure",
+ action='store_true', dest="stop_on_fail", default=False)
parser.add_option_group(group)
group = OptionGroup(parser, "Test Selection")
group.add_option("", "--test", help="Run a particular test",
type=int, dest="test", default=None, metavar="INDEX")
group.add_option("", "--max-tests", help="Maximum number of tests",
- type=int, dest="max_tests", default=10, metavar="COUNT")
+ type=int, dest="max_tests", default=None, metavar="COUNT")
group.add_option("", "--pick-input",
help="Randomly select an input byte as well as fuzzing",
action='store_true', dest="pick_input", default=False)
@@ -329,7 +336,10 @@ and you can run a particular test with '--test <index>'.
ta = TestApplication(tg, t)
try:
ta.apply()
- run_one_test(ta, test, input_files, args)
+ test_result = run_one_test(ta, test, input_files, args)
+ if not test_result and opts.stop_on_fail:
+ opts.revert = False
+ sys.exit(1)
finally:
if opts.revert:
ta.revert()
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index 75a616700405..0d879214d4a2 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -1,5 +1,6 @@
set(LLVM_REQUIRES_EH 1)
set(LLVM_REQUIRES_RTTI 1)
+set(LLVM_LINK_COMPONENTS Support)
add_tablegen(clang-tblgen CLANG
ClangASTNodesEmitter.cpp
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index 5c236be559f1..7951fc467d20 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -16,6 +16,7 @@
#include "llvm/TableGen/Record.h"
#include <algorithm>
#include <cctype>
+#include <set>
using namespace llvm;
@@ -33,8 +34,6 @@ getValueAsListOfStrings(Record &R, StringRef FieldName) {
assert(*i && "Got a null element in a ListInit");
if (StringInit *S = dynamic_cast<StringInit *>(*i))
Strings.push_back(S->getValue());
- else if (CodeInit *C = dynamic_cast<CodeInit *>(*i))
- Strings.push_back(C->getValue());
else
assert(false && "Got a non-string, non-code element in a ListInit");
}
@@ -67,6 +66,30 @@ static std::string WritePCHRecord(StringRef type, StringRef name) {
.Default("Record.push_back(" + std::string(name) + ");\n");
}
+// Normalize attribute name by removing leading and trailing
+// underscores. For example, __foo, foo__, __foo__ would
+// become foo.
+static StringRef NormalizeAttrName(StringRef AttrName) {
+ if (AttrName.startswith("__"))
+ AttrName = AttrName.substr(2, AttrName.size());
+
+ if (AttrName.endswith("__"))
+ AttrName = AttrName.substr(0, AttrName.size() - 2);
+
+ return AttrName;
+}
+
+// Normalize attribute spelling only if the spelling has both leading
+// and trailing underscores. For example, __ms_struct__ will be
+// normalized to "ms_struct"; __cdecl will remain intact.
+static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
+ if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
+ AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
+ }
+
+ return AttrSpelling;
+}
+
namespace {
class Argument {
std::string lowerName, upperName;
@@ -91,6 +114,8 @@ namespace {
virtual void writeAccessors(raw_ostream &OS) const = 0;
virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
virtual void writeCloneArgs(raw_ostream &OS) const = 0;
+ virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
+ virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
virtual void writeCtorBody(raw_ostream &OS) const {}
virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
virtual void writeCtorParameters(raw_ostream &OS) const = 0;
@@ -98,6 +123,7 @@ namespace {
virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
virtual void writePCHWrite(raw_ostream &OS) const = 0;
+ virtual void writeValue(raw_ostream &OS) const = 0;
};
class SimpleArgument : public Argument {
@@ -108,6 +134,8 @@ namespace {
: Argument(Arg, Attr), type(T)
{}
+ std::string getType() const { return type; }
+
void writeAccessors(raw_ostream &OS) const {
OS << " " << type << " get" << getUpperName() << "() const {\n";
OS << " return " << getLowerName() << ";\n";
@@ -116,6 +144,9 @@ namespace {
void writeCloneArgs(raw_ostream &OS) const {
OS << getLowerName();
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "A->get" << getUpperName() << "()";
+ }
void writeCtorInitializers(raw_ostream &OS) const {
OS << getLowerName() << "(" << getUpperName() << ")";
}
@@ -136,6 +167,19 @@ namespace {
OS << " " << WritePCHRecord(type, "SA->get" +
std::string(getUpperName()) + "()");
}
+ void writeValue(raw_ostream &OS) const {
+ if (type == "FunctionDecl *") {
+ OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \"";
+ } else if (type == "IdentifierInfo *") {
+ OS << "\" << get" << getUpperName() << "()->getName() << \"";
+ } else if (type == "QualType") {
+ OS << "\" << get" << getUpperName() << "().getAsString() << \"";
+ } else if (type == "SourceLocation") {
+ OS << "\" << get" << getUpperName() << "().getRawEncoding() << \"";
+ } else {
+ OS << "\" << get" << getUpperName() << "() << \"";
+ }
+ }
};
class StringArgument : public Argument {
@@ -164,6 +208,9 @@ namespace {
void writeCloneArgs(raw_ostream &OS) const {
OS << "get" << getUpperName() << "()";
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "A->get" << getUpperName() << "()";
+ }
void writeCtorBody(raw_ostream &OS) const {
OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
<< ".data(), " << getLowerName() << "Length);";
@@ -190,6 +237,9 @@ namespace {
void writePCHWrite(raw_ostream &OS) const {
OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
}
+ void writeValue(raw_ostream &OS) const {
+ OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
+ }
};
class AlignedArgument : public Argument {
@@ -251,6 +301,10 @@ namespace {
<< "Expr) : " << getLowerName()
<< "Type";
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ // FIXME: move the definition in Sema::InstantiateAttrs to here.
+ // In the meantime, aligned attributes are cloned.
+ }
void writeCtorBody(raw_ostream &OS) const {
OS << " if (is" << getLowerName() << "Expr)\n";
OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
@@ -293,6 +347,9 @@ namespace {
OS << " AddTypeSourceInfo(SA->get" << getUpperName()
<< "Type(), Record);\n";
}
+ void writeValue(raw_ostream &OS) const {
+ OS << "\" << get" << getUpperName() << "(Ctx) << \"";
+ }
};
class VariadicArgument : public Argument {
@@ -317,12 +374,17 @@ namespace {
<< "Size;\n";
OS << " }\n";
OS << " unsigned " << getLowerName() << "_size() const {\n"
- << " return " << getLowerName() << "Size;\n;";
+ << " return " << getLowerName() << "Size;\n";
OS << " }";
}
void writeCloneArgs(raw_ostream &OS) const {
OS << getLowerName() << ", " << getLowerName() << "Size";
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ // This isn't elegant, but we have to go through public methods...
+ OS << "A->" << getLowerName() << "_begin(), "
+ << "A->" << getLowerName() << "_size()";
+ }
void writeCtorBody(raw_ostream &OS) const {
// FIXME: memcpy is not safe on non-trivial types.
OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
@@ -362,6 +424,18 @@ namespace {
<< getLowerName() << "_end(); i != e; ++i)\n";
OS << " " << WritePCHRecord(type, "(*i)");
}
+ void writeValue(raw_ostream &OS) const {
+ OS << "\";\n";
+ OS << " bool isFirst = true;\n"
+ << " for (" << getAttrName() << "Attr::" << getLowerName()
+ << "_iterator i = " << getLowerName() << "_begin(), e = "
+ << getLowerName() << "_end(); i != e; ++i) {\n"
+ << " if (isFirst) isFirst = false;\n"
+ << " else OS << \", \";\n"
+ << " OS << *i;\n"
+ << " }\n";
+ OS << " OS << \"";
+ }
};
class EnumArgument : public Argument {
@@ -382,6 +456,9 @@ namespace {
void writeCloneArgs(raw_ostream &OS) const {
OS << getLowerName();
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "A->get" << getUpperName() << "()";
+ }
void writeCtorInitializers(raw_ostream &OS) const {
OS << getLowerName() << "(" << getUpperName() << ")";
}
@@ -422,6 +499,9 @@ namespace {
void writePCHWrite(raw_ostream &OS) const {
OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
}
+ void writeValue(raw_ostream &OS) const {
+ OS << "\" << get" << getUpperName() << "() << \"";
+ }
};
class VersionArgument : public Argument {
@@ -442,6 +522,9 @@ namespace {
void writeCloneArgs(raw_ostream &OS) const {
OS << "get" << getUpperName() << "()";
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "A->get" << getUpperName() << "()";
+ }
void writeCtorBody(raw_ostream &OS) const {
}
void writeCtorInitializers(raw_ostream &OS) const {
@@ -463,6 +546,64 @@ namespace {
void writePCHWrite(raw_ostream &OS) const {
OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
}
+ void writeValue(raw_ostream &OS) const {
+ OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
+ }
+ };
+
+ class ExprArgument : public SimpleArgument {
+ public:
+ ExprArgument(Record &Arg, StringRef Attr)
+ : SimpleArgument(Arg, Attr, "Expr *")
+ {}
+
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "tempInst" << getUpperName();
+ }
+
+ void writeTemplateInstantiation(raw_ostream &OS) const {
+ OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
+ OS << " {\n";
+ OS << " EnterExpressionEvaluationContext "
+ << "Unevaluated(S, Sema::Unevaluated);\n";
+ OS << " ExprResult " << "Result = S.SubstExpr("
+ << "A->get" << getUpperName() << "(), TemplateArgs);\n";
+ OS << " tempInst" << getUpperName() << " = "
+ << "Result.takeAs<Expr>();\n";
+ OS << " }\n";
+ }
+ };
+
+ class VariadicExprArgument : public VariadicArgument {
+ public:
+ VariadicExprArgument(Record &Arg, StringRef Attr)
+ : VariadicArgument(Arg, Attr, "Expr *")
+ {}
+
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "tempInst" << getUpperName() << ", "
+ << "A->" << getLowerName() << "_size()";
+ }
+
+ void writeTemplateInstantiation(raw_ostream &OS) const {
+ OS << " " << getType() << " *tempInst" << getUpperName()
+ << " = new (C, 16) " << getType()
+ << "[A->" << getLowerName() << "_size()];\n";
+ OS << " {\n";
+ OS << " EnterExpressionEvaluationContext "
+ << "Unevaluated(S, Sema::Unevaluated);\n";
+ OS << " " << getType() << " *TI = tempInst" << getUpperName()
+ << ";\n";
+ OS << " " << getType() << " *I = A->" << getLowerName()
+ << "_begin();\n";
+ OS << " " << getType() << " *E = A->" << getLowerName()
+ << "_end();\n";
+ OS << " for (; I != E; ++I, ++TI) {\n";
+ OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
+ OS << " *TI = Result.takeAs<Expr>();\n";
+ OS << " }\n";
+ OS << " }\n";
+ }
};
}
@@ -476,8 +617,7 @@ static Argument *createArgument(Record &Arg, StringRef Attr,
if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
- else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
- "Expr *");
+ else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
else if (ArgName == "FunctionArgument")
Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
else if (ArgName == "IdentifierArgument")
@@ -495,7 +635,7 @@ static Argument *createArgument(Record &Arg, StringRef Attr,
else if (ArgName == "VariadicUnsignedArgument")
Ptr = new VariadicArgument(Arg, Attr, "unsigned");
else if (ArgName == "VariadicExprArgument")
- Ptr = new VariadicArgument(Arg, Attr, "Expr *");
+ Ptr = new VariadicExprArgument(Arg, Attr);
else if (ArgName == "VersionArgument")
Ptr = new VersionArgument(Arg, Attr);
@@ -511,6 +651,15 @@ static Argument *createArgument(Record &Arg, StringRef Attr,
return Ptr;
}
+static void writeAvailabilityValue(raw_ostream &OS) {
+ OS << "\" << getPlatform()->getName();\n"
+ << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
+ << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
+ << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
+ << " if (getUnavailable()) OS << \", unavailable\";\n"
+ << " OS << \"";
+}
+
void ClangAttrClassEmitter::run(raw_ostream &OS) {
OS << "// This file is generated by TableGen. Do not edit.\n\n";
OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
@@ -571,19 +720,25 @@ void ClangAttrClassEmitter::run(raw_ostream &OS) {
OS << " }\n\n";
OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
+ OS << " virtual void printPretty(llvm::raw_ostream &OS, ASTContext &Ctx) const;\n";
for (ai = Args.begin(); ai != ae; ++ai) {
(*ai)->writeAccessors(OS);
OS << "\n\n";
}
- OS << R.getValueAsCode("AdditionalMembers");
+ OS << R.getValueAsString("AdditionalMembers");
OS << "\n\n";
OS << " static bool classof(const Attr *A) { return A->getKind() == "
<< "attr::" << R.getName() << "; }\n";
OS << " static bool classof(const " << R.getName()
<< "Attr *) { return true; }\n";
+
+ bool LateParsed = R.getValueAsBit("LateParsed");
+ OS << " virtual bool isLateParsed() const { return "
+ << LateParsed << "; }\n";
+
OS << "};\n\n";
}
@@ -600,6 +755,7 @@ void ClangAttrImplEmitter::run(raw_ostream &OS) {
for (; i != e; ++i) {
Record &R = **i;
std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
+ std::vector<StringRef> Spellings = getValueAsListOfStrings(R, "Spellings");
std::vector<Argument*> Args;
for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
Args.push_back(createArgument(**ri, R.getName()));
@@ -615,6 +771,24 @@ void ClangAttrImplEmitter::run(raw_ostream &OS) {
(*ai)->writeCloneArgs(OS);
}
OS << ");\n}\n\n";
+
+ OS << "void " << R.getName() << "Attr::printPretty("
+ << "llvm::raw_ostream &OS, ASTContext &Ctx) const {\n";
+ if (Spellings.begin() != Spellings.end()) {
+ OS << " OS << \" __attribute__((" << *Spellings.begin();
+ if (Args.size()) OS << "(";
+ if (*Spellings.begin()=="availability") {
+ writeAvailabilityValue(OS);
+ } else {
+ for (ai = Args.begin(); ai != ae; ++ai) {
+ if (ai!=Args.begin()) OS <<", ";
+ (*ai)->writeValue(OS);
+ }
+ }
+ if (Args.size()) OS << ")";
+ OS << "))\";\n";
+ }
+ OS << "}\n\n";
}
}
@@ -786,3 +960,133 @@ void ClangAttrLateParsedListEmitter::run(raw_ostream &OS) {
}
}
}
+
+
+void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+
+ OS << "namespace clang {\n"
+ << "namespace sema {\n\n"
+ << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
+ << "Sema &S,\n"
+ << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
+ << " switch (At->getKind()) {\n"
+ << " default:\n"
+ << " break;\n";
+
+ for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
+ I != E; ++I) {
+ Record &R = **I;
+
+ OS << " case attr::" << R.getName() << ": {\n";
+ OS << " const " << R.getName() << "Attr *A = cast<"
+ << R.getName() << "Attr>(At);\n";
+ bool TDependent = R.getValueAsBit("TemplateDependent");
+
+ if (!TDependent) {
+ OS << " return A->clone(C);\n";
+ OS << " }\n";
+ continue;
+ }
+
+ std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
+ std::vector<Argument*> Args;
+ std::vector<Argument*>::iterator ai, ae;
+ Args.reserve(ArgRecords.size());
+
+ for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
+ re = ArgRecords.end();
+ ri != re; ++ri) {
+ Record &ArgRecord = **ri;
+ Argument *Arg = createArgument(ArgRecord, R.getName());
+ assert(Arg);
+ Args.push_back(Arg);
+ }
+ ae = Args.end();
+
+ for (ai = Args.begin(); ai != ae; ++ai) {
+ (*ai)->writeTemplateInstantiation(OS);
+ }
+ OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
+ for (ai = Args.begin(); ai != ae; ++ai) {
+ OS << ", ";
+ (*ai)->writeTemplateInstantiationArgs(OS);
+ }
+ OS << ");\n }\n";
+ }
+ OS << " } // end switch\n"
+ << " llvm_unreachable(\"Unknown attribute!\");\n"
+ << " return 0;\n"
+ << "}\n\n"
+ << "} // end namespace sema\n"
+ << "} // end namespace clang\n";
+}
+
+void ClangAttrParsedAttrListEmitter::run(raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+ OS << "#ifndef PARSED_ATTR\n";
+ OS << "#define PARSED_ATTR(NAME) NAME\n";
+ OS << "#endif\n\n";
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+ std::set<StringRef> ProcessedAttrs;
+
+ for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
+ I != E; ++I) {
+ Record &Attr = **I;
+
+ bool SemaHandler = Attr.getValueAsBit("SemaHandler");
+
+ if (SemaHandler) {
+ std::vector<StringRef> Spellings =
+ getValueAsListOfStrings(Attr, "Spellings");
+
+ for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
+ E = Spellings.end(); I != E; ++I) {
+ StringRef AttrName = *I;
+
+ AttrName = NormalizeAttrName(AttrName);
+ // skip if a normalized version has been processed.
+ if (ProcessedAttrs.find(AttrName) != ProcessedAttrs.end())
+ continue;
+ else
+ ProcessedAttrs.insert(AttrName);
+
+ OS << "PARSED_ATTR(" << AttrName << ")\n";
+ }
+ }
+ }
+}
+
+void ClangAttrParsedAttrKindsEmitter::run(raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+
+ for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
+ I != E; ++I) {
+ Record &Attr = **I;
+
+ bool SemaHandler = Attr.getValueAsBit("SemaHandler");
+
+ if (SemaHandler) {
+ std::vector<StringRef> Spellings =
+ getValueAsListOfStrings(Attr, "Spellings");
+
+ for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
+ E = Spellings.end(); I != E; ++I) {
+ StringRef AttrName = *I, Spelling = *I;
+
+ AttrName = NormalizeAttrName(AttrName);
+ Spelling = NormalizeAttrSpelling(Spelling);
+
+ OS << ".Case(\"" << Spelling << "\", " << "AT_" << AttrName << ")\n";
+ }
+ }
+ }
+}
+
+
diff --git a/utils/TableGen/ClangAttrEmitter.h b/utils/TableGen/ClangAttrEmitter.h
index 5acca560f013..d119a094c177 100644
--- a/utils/TableGen/ClangAttrEmitter.h
+++ b/utils/TableGen/ClangAttrEmitter.h
@@ -109,6 +109,45 @@ class ClangAttrLateParsedListEmitter : public TableGenBackend {
void run(raw_ostream &OS);
};
+/// ClangAttrTemplateInstantiateEmitter emits code to instantiate dependent
+/// attributes on templates.
+class ClangAttrTemplateInstantiateEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+ public:
+ explicit ClangAttrTemplateInstantiateEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+};
+
+/// ClangAttrParsedAttrListEmitter emits the list of parsed attributes
+/// for clang.
+class ClangAttrParsedAttrListEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+public:
+ explicit ClangAttrParsedAttrListEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+};
+
+/// ClangAttrParsedAttrKindsEmitter emits the kind list of parsed attributes
+/// for clang.
+class ClangAttrParsedAttrKindsEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+public:
+ explicit ClangAttrParsedAttrKindsEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+};
+
}
#endif
diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp
index da2fb70b4a57..8a49619c725e 100644
--- a/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -16,13 +16,12 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/VectorExtras.h"
#include <map>
#include <algorithm>
#include <functional>
+#include <set>
using namespace llvm;
//===----------------------------------------------------------------------===//
@@ -51,7 +50,6 @@ public:
};
} // end anonymous namespace.
-
static std::string
getCategoryFromDiagGroup(const Record *Group,
DiagGroupParentMap &DiagGroupParents) {
@@ -120,8 +118,44 @@ namespace {
iterator begin() { return CategoryStrings.begin(); }
iterator end() { return CategoryStrings.end(); }
};
+
+ struct GroupInfo {
+ std::vector<const Record*> DiagsInGroup;
+ std::vector<std::string> SubGroups;
+ unsigned IDNo;
+ };
} // end anonymous namespace.
+/// \brief Invert the 1-[0/1] mapping of diags to group into a one to many
+/// mapping of groups to diags in the group.
+static void groupDiagnostics(const std::vector<Record*> &Diags,
+ const std::vector<Record*> &DiagGroups,
+ std::map<std::string, GroupInfo> &DiagsInGroup) {
+ for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+ const Record *R = Diags[i];
+ DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group"));
+ if (DI == 0) continue;
+ std::string GroupName = DI->getDef()->getValueAsString("GroupName");
+ DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
+ }
+
+ // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
+ // groups (these are warnings that GCC supports that clang never produces).
+ for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
+ Record *Group = DiagGroups[i];
+ GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
+
+ std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
+ for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
+ GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
+ }
+
+ // Assign unique ID numbers to the groups.
+ unsigned IDNo = 0;
+ for (std::map<std::string, GroupInfo>::iterator
+ I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
+ I->second.IDNo = IDNo;
+}
//===----------------------------------------------------------------------===//
// Warning Tables (.inc file) generation.
@@ -130,7 +164,7 @@ namespace {
void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
// Write the #if guard
if (!Component.empty()) {
- std::string ComponentName = UppercaseString(Component);
+ std::string ComponentName = StringRef(Component).upper();
OS << "#ifdef " << ComponentName << "START\n";
OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
<< ",\n";
@@ -140,7 +174,13 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
const std::vector<Record*> &Diags =
Records.getAllDerivedDefinitions("Diagnostic");
-
+
+ std::vector<Record*> DiagGroups
+ = Records.getAllDerivedDefinitions("DiagGroup");
+
+ std::map<std::string, GroupInfo> DiagsInGroup;
+ groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
+
DiagCategoryIDMap CategoryIDs(Records);
DiagGroupParentMap DGParentMap(Records);
@@ -158,12 +198,15 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
OS << ", \"";
OS.write_escaped(R.getValueAsString("Text")) << '"';
- // Warning associated with the diagnostic.
+ // Warning associated with the diagnostic. This is stored as an index into
+ // the alphabetically sorted warning table.
if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group"))) {
- OS << ", \"";
- OS.write_escaped(DI->getDef()->getValueAsString("GroupName")) << '"';
+ std::map<std::string, GroupInfo>::iterator I =
+ DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName"));
+ assert(I != DiagsInGroup.end());
+ OS << ", " << I->second.IDNo;
} else {
- OS << ", \"\"";
+ OS << ", 0";
}
// SFINAE bit
@@ -196,14 +239,6 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
// Category number.
OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
-
- // Brief
- OS << ", \"";
- OS.write_escaped(R.getValueAsString("Brief")) << '"';
-
- // Explanation
- OS << ", \"";
- OS.write_escaped(R.getValueAsString("Explanation")) << '"';
OS << ")\n";
}
}
@@ -215,56 +250,24 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) {
static std::string getDiagCategoryEnum(llvm::StringRef name) {
if (name.empty())
return "DiagCat_None";
- llvm::SmallString<256> enumName = llvm::StringRef("DiagCat_");
+ SmallString<256> enumName = llvm::StringRef("DiagCat_");
for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
enumName += isalnum(*I) ? *I : '_';
return enumName.str();
}
-namespace {
-struct GroupInfo {
- std::vector<const Record*> DiagsInGroup;
- std::vector<std::string> SubGroups;
- unsigned IDNo;
-};
-} // end anonymous namespace.
-
void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
// Compute a mapping from a DiagGroup to all of its parents.
DiagGroupParentMap DGParentMap(Records);
- // Invert the 1-[0/1] mapping of diags to group into a one to many mapping of
- // groups to diags in the group.
- std::map<std::string, GroupInfo> DiagsInGroup;
-
std::vector<Record*> Diags =
Records.getAllDerivedDefinitions("Diagnostic");
- for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
- const Record *R = Diags[i];
- DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group"));
- if (DI == 0) continue;
- std::string GroupName = DI->getDef()->getValueAsString("GroupName");
- DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
- }
- // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
- // groups (these are warnings that GCC supports that clang never produces).
std::vector<Record*> DiagGroups
= Records.getAllDerivedDefinitions("DiagGroup");
- for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
- Record *Group = DiagGroups[i];
- GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
-
- std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
- for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
- GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
- }
-
- // Assign unique ID numbers to the groups.
- unsigned IDNo = 0;
- for (std::map<std::string, GroupInfo>::iterator
- I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
- I->second.IDNo = IDNo;
+
+ std::map<std::string, GroupInfo> DiagsInGroup;
+ groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
// Walk through the groups emitting an array for each diagnostic of the diags
// that are mapped to.
@@ -304,6 +307,10 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
OS << " { ";
OS << I->first.size() << ", ";
OS << "\"";
+ if (I->first.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789!@#$%^*-+=:?")!=std::string::npos)
+ throw "Invalid character in diagnostic group '" + I->first + "'";
OS.write_escaped(I->first) << "\","
<< std::string(MaxLen-I->first.size()+1, ' ');
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index 66845ccacb32..e6f2e53aa706 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -28,6 +28,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
#include <string>
using namespace llvm;
@@ -56,7 +57,6 @@ static void ParseTypes(Record *r, std::string &s,
default:
throw TGError(r->getLoc(),
"Unexpected letter: " + std::string(data + len, 1));
- break;
}
TV.push_back(StringRef(data, len + 1));
data += len + 1;
@@ -78,7 +78,6 @@ static char Widen(const char t) {
return 'f';
default: throw "unhandled type in widen!";
}
- return '\0';
}
/// Narrow - Convert a type code into the next smaller type. short -> char,
@@ -95,7 +94,6 @@ static char Narrow(const char t) {
return 'h';
default: throw "unhandled type in narrow!";
}
- return '\0';
}
/// For a particular StringRef, return the base type code, and whether it has
@@ -266,7 +264,6 @@ static std::string TypeString(const char mod, StringRef typestr) {
break;
default:
throw "unhandled type!";
- break;
}
if (mod == '2')
@@ -449,7 +446,6 @@ static std::string MangleName(const std::string &name, StringRef typestr,
break;
default:
throw "unhandled type!";
- break;
}
if (ck == ClassB)
s += "_v";
@@ -526,12 +522,6 @@ static std::string GenMacroLocals(const std::string &proto, StringRef typestr) {
for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
// Do not create a temporary for an immediate argument.
// That would defeat the whole point of using a macro!
- // FIXME: For other (non-immediate) arguments that are used directly, a
- // local temporary (or some other method) is still needed to get the
- // correct type checking, even if that temporary is not used for anything.
- // This is omitted for now because it turns out the the use of
- // "__extension__" in the macro disables any warnings from the pointer
- // assignment.
if (MacroArgUsedDirectly(proto, i))
continue;
generatedLocal = true;
@@ -594,7 +584,6 @@ static unsigned GetNumElements(StringRef typestr, bool &quad) {
case 'f': nElts = 2; break;
default:
throw "unhandled type!";
- break;
}
if (quad) nElts <<= 1;
return nElts;
@@ -826,14 +815,12 @@ static std::string GenOpString(OpKind op, const std::string &proto,
}
default:
throw "unknown OpKind!";
- break;
}
return s;
}
static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
unsigned mod = proto[0];
- unsigned ret = 0;
if (mod == 'v' || mod == 'f')
mod = proto[1];
@@ -851,35 +838,31 @@ static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
// Based on the modifying character, change the type and width if necessary.
type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
- if (usgn)
- ret |= 0x08;
- if (quad && proto[1] != 'g')
- ret |= 0x10;
-
+ NeonTypeFlags::EltType ET;
switch (type) {
case 'c':
- ret |= poly ? 5 : 0;
+ ET = poly ? NeonTypeFlags::Poly8 : NeonTypeFlags::Int8;
break;
case 's':
- ret |= poly ? 6 : 1;
+ ET = poly ? NeonTypeFlags::Poly16 : NeonTypeFlags::Int16;
break;
case 'i':
- ret |= 2;
+ ET = NeonTypeFlags::Int32;
break;
case 'l':
- ret |= 3;
+ ET = NeonTypeFlags::Int64;
break;
case 'h':
- ret |= 7;
+ ET = NeonTypeFlags::Float16;
break;
case 'f':
- ret |= 4;
+ ET = NeonTypeFlags::Float32;
break;
default:
throw "unhandled type!";
- break;
}
- return ret;
+ NeonTypeFlags Flags(ET, usgn, quad && proto[1] != 'g');
+ return Flags.getFlags();
}
// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
@@ -1249,10 +1232,7 @@ static unsigned RangeFromType(const char mod, StringRef typestr) {
return (1 << (int)quad) - 1;
default:
throw "unhandled type!";
- break;
}
- assert(0 && "unreachable");
- return 0;
}
/// runHeader - Emit a file with sections defining:
@@ -1346,14 +1326,57 @@ void NeonEmitter::runHeader(raw_ostream &OS) {
mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
}
}
- if (mask)
+
+ // Check if the builtin function has a pointer or const pointer argument.
+ int PtrArgNum = -1;
+ bool HasConstPtr = false;
+ for (unsigned arg = 1, arge = Proto.size(); arg != arge; ++arg) {
+ char ArgType = Proto[arg];
+ if (ArgType == 'c') {
+ HasConstPtr = true;
+ PtrArgNum = arg - 1;
+ break;
+ }
+ if (ArgType == 'p') {
+ PtrArgNum = arg - 1;
+ break;
+ }
+ }
+ // For sret builtins, adjust the pointer argument index.
+ if (PtrArgNum >= 0 && (Proto[0] >= '2' && Proto[0] <= '4'))
+ PtrArgNum += 1;
+
+ // Omit type checking for the pointer arguments of vld1_lane, vld1_dup,
+ // and vst1_lane intrinsics. Using a pointer to the vector element
+ // type with one of those operations causes codegen to select an aligned
+ // load/store instruction. If you want an unaligned operation,
+ // the pointer argument needs to have less alignment than element type,
+ // so just accept any pointer type.
+ if (name == "vld1_lane" || name == "vld1_dup" || name == "vst1_lane") {
+ PtrArgNum = -1;
+ HasConstPtr = false;
+ }
+
+ if (mask) {
OS << "case ARM::BI__builtin_neon_"
<< MangleName(name, TypeVec[si], ClassB)
- << ": mask = " << "0x" << utohexstr(mask) << "; break;\n";
- if (qmask)
+ << ": mask = " << "0x" << utohexstr(mask);
+ if (PtrArgNum >= 0)
+ OS << "; PtrArgNum = " << PtrArgNum;
+ if (HasConstPtr)
+ OS << "; HasConstPtr = true";
+ OS << "; break;\n";
+ }
+ if (qmask) {
OS << "case ARM::BI__builtin_neon_"
<< MangleName(name, TypeVec[qi], ClassB)
- << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n";
+ << ": mask = " << "0x" << utohexstr(qmask);
+ if (PtrArgNum >= 0)
+ OS << "; PtrArgNum = " << PtrArgNum;
+ if (HasConstPtr)
+ OS << "; HasConstPtr = true";
+ OS << "; break;\n";
+ }
}
OS << "#endif\n\n";
diff --git a/utils/TableGen/NeonEmitter.h b/utils/TableGen/NeonEmitter.h
index 708ad3c06a0f..dec745111164 100644
--- a/utils/TableGen/NeonEmitter.h
+++ b/utils/TableGen/NeonEmitter.h
@@ -86,6 +86,40 @@ enum ClassKind {
ClassB // bitcast arguments with enum argument to specify type
};
+/// NeonTypeFlags - Flags to identify the types for overloaded Neon
+/// builtins. These must be kept in sync with the flags in
+/// include/clang/Basic/TargetBuiltins.h.
+class NeonTypeFlags {
+ enum {
+ EltTypeMask = 0xf,
+ UnsignedFlag = 0x10,
+ QuadFlag = 0x20
+ };
+ uint32_t Flags;
+
+public:
+ enum EltType {
+ Int8,
+ Int16,
+ Int32,
+ Int64,
+ Poly8,
+ Poly16,
+ Float16,
+ Float32
+ };
+
+ NeonTypeFlags(unsigned F) : Flags(F) {}
+ NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) {
+ if (IsUnsigned)
+ Flags |= UnsignedFlag;
+ if (IsQuad)
+ Flags |= QuadFlag;
+ }
+
+ uint32_t getFlags() const { return Flags; }
+};
+
namespace llvm {
class NeonEmitter : public TableGenBackend {
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index 5c016d32ddd7..5ff88db30156 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -36,6 +36,9 @@ enum ActionType {
GenClangAttrPCHWrite,
GenClangAttrSpellingList,
GenClangAttrLateParsedList,
+ GenClangAttrTemplateInstantiate,
+ GenClangAttrParsedAttrList,
+ GenClangAttrParsedAttrKinds,
GenClangDiagsDefs,
GenClangDiagGroups,
GenClangDiagsIndexName,
@@ -71,6 +74,15 @@ namespace {
clEnumValN(GenClangAttrLateParsedList,
"gen-clang-attr-late-parsed-list",
"Generate a clang attribute LateParsed list"),
+ clEnumValN(GenClangAttrTemplateInstantiate,
+ "gen-clang-attr-template-instantiate",
+ "Generate a clang template instantiate code"),
+ clEnumValN(GenClangAttrParsedAttrList,
+ "gen-clang-attr-parsed-attr-list",
+ "Generate a clang parsed attribute list"),
+ clEnumValN(GenClangAttrParsedAttrKinds,
+ "gen-clang-attr-parsed-attr-kinds",
+ "Generate a clang parsed attribute kinds"),
clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
"Generate Clang diagnostics definitions"),
clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
@@ -96,7 +108,6 @@ namespace {
ClangComponent("clang-component",
cl::desc("Only use warnings from specified component"),
cl::value_desc("component"), cl::Hidden);
-}
class ClangTableGenAction : public TableGenAction {
public:
@@ -123,6 +134,15 @@ public:
case GenClangAttrLateParsedList:
ClangAttrLateParsedListEmitter(Records).run(OS);
break;
+ case GenClangAttrTemplateInstantiate:
+ ClangAttrTemplateInstantiateEmitter(Records).run(OS);
+ break;
+ case GenClangAttrParsedAttrList:
+ ClangAttrParsedAttrListEmitter(Records).run(OS);
+ break;
+ case GenClangAttrParsedAttrKinds:
+ ClangAttrParsedAttrKindsEmitter(Records).run(OS);
+ break;
case GenClangDiagsDefs:
ClangDiagsDefsEmitter(Records, ClangComponent).run(OS);
break;
@@ -157,14 +177,12 @@ public:
case GenArmNeonTest:
NeonEmitter(Records).runTests(OS);
break;
- default:
- assert(1 && "Invalid Action");
- return true;
}
return false;
}
};
+}
int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal();
diff --git a/utils/analyzer/CmpRuns.py b/utils/analyzer/CmpRuns.py
index 8eba9ebc7bcd..e68c45df184a 100755
--- a/utils/analyzer/CmpRuns.py
+++ b/utils/analyzer/CmpRuns.py
@@ -65,18 +65,22 @@ class AnalysisDiagnostic:
filename = self.report.run.getSourceName(self.report.files[loc['file']])
line = loc['line']
column = loc['col']
+ category = self.data['category']
+ description = self.data['description']
# FIXME: Get a report number based on this key, to 'distinguish'
# reports, or something.
- return '%s:%d:%d' % (filename, line, column)
+ return '%s:%d:%d, %s: %s' % (filename, line, column, category,
+ description)
def getReportData(self):
if self.htmlReport is None:
- return "This diagnostic does not have any report data."
-
- return open(os.path.join(self.report.run.path,
- self.htmlReport), "rb").read()
+ return " "
+ return os.path.join(self.report.run.path, self.htmlReport)
+ # We could also dump the report with:
+ # return open(os.path.join(self.report.run.path,
+ # self.htmlReport), "rb").read()
class AnalysisRun:
def __init__(self, path, opts):
@@ -153,7 +157,7 @@ def compareResults(A, B):
while eltsA and eltsB:
a = eltsA.pop()
b = eltsB.pop()
- if a.data == b.data:
+ if a.data['location'] == b.data['location']:
res.append((a, b, 0))
elif a.data > b.data:
neqA.append(a)
@@ -189,25 +193,25 @@ def cmpScanBuildResults(dirA, dirB, opts, deleteEmpty=True):
auxLog = None
diff = compareResults(resultsA, resultsB)
- foundDiffs = False
+ foundDiffs = 0
for res in diff:
a,b,confidence = res
if a is None:
print "ADDED: %r" % b.getReadableName()
- foundDiffs = True
+ foundDiffs += 1
if auxLog:
print >>auxLog, ("('ADDED', %r, %r)" % (b.getReadableName(),
b.getReportData()))
elif b is None:
print "REMOVED: %r" % a.getReadableName()
- foundDiffs = True
+ foundDiffs += 1
if auxLog:
print >>auxLog, ("('REMOVED', %r, %r)" % (a.getReadableName(),
a.getReportData()))
elif confidence:
print "CHANGED: %r to %r" % (a.getReadableName(),
b.getReadableName())
- foundDiffs = True
+ foundDiffs += 1
if auxLog:
print >>auxLog, ("('CHANGED', %r, %r, %r, %r)"
% (a.getReadableName(),
@@ -217,10 +221,13 @@ def cmpScanBuildResults(dirA, dirB, opts, deleteEmpty=True):
else:
pass
- print "TOTAL REPORTS: %r" % len(resultsB.diagnostics)
+ TotalReports = len(resultsB.diagnostics)
+ print "TOTAL REPORTS: %r" % TotalReports
+ print "TOTAL DIFFERENCES: %r" % foundDiffs
if auxLog:
- print >>auxLog, "('TOTAL REPORTS', %r)" % len(resultsB.diagnostics)
-
+ print >>auxLog, "('TOTAL NEW REPORTS', %r)" % TotalReports
+ print >>auxLog, "('TOTAL DIFFERENCES', %r)" % foundDiffs
+
return foundDiffs
def main():
diff --git a/utils/analyzer/SATestAdd.py b/utils/analyzer/SATestAdd.py
index 9fab07bfa9f0..ce64bc82f756 100644
--- a/utils/analyzer/SATestAdd.py
+++ b/utils/analyzer/SATestAdd.py
@@ -22,11 +22,18 @@ import os
import csv
import sys
+def isExistingProject(PMapFile, projectID) :
+ PMapReader = csv.reader(PMapFile)
+ for I in PMapReader:
+ if projectID == I[0]:
+ return True
+ return False
+
# Add a new project for testing: build it and add to the Project Map file.
# Params:
# Dir is the directory where the sources are.
# ID is a short string used to identify a project.
-def addNewProject(ID) :
+def addNewProject(ID, IsScanBuild) :
CurDir = os.path.abspath(os.curdir)
Dir = SATestBuild.getProjectDir(ID)
if not os.path.exists(Dir):
@@ -34,7 +41,7 @@ def addNewProject(ID) :
sys.exit(-1)
# Build the project.
- SATestBuild.testProject(ID, True, Dir)
+ SATestBuild.testProject(ID, True, IsScanBuild, Dir)
# Add the project ID to the project map.
ProjectMapPath = os.path.join(CurDir, SATestBuild.ProjectMapFile)
@@ -44,20 +51,16 @@ def addNewProject(ID) :
print "Warning: Creating the Project Map file!!"
PMapFile = open(ProjectMapPath, "w+b")
try:
- PMapReader = csv.reader(PMapFile)
- for I in PMapReader:
- IID = I[0]
- if ID == IID:
- print >> sys.stderr, 'Warning: Project with ID \'', ID, \
- '\' already exists.'
- sys.exit(-1)
-
- PMapWriter = csv.writer(PMapFile)
- PMapWriter.writerow( (ID, Dir) );
+ if (isExistingProject(PMapFile, ID)) :
+ print >> sys.stdout, 'Warning: Project with ID \'', ID, \
+ '\' already exists.'
+ print >> sys.stdout, "Reference output has been regenerated."
+ else:
+ PMapWriter = csv.writer(PMapFile)
+ PMapWriter.writerow( (ID, int(IsScanBuild)) );
+ print "The project map is updated: ", ProjectMapPath
finally:
PMapFile.close()
-
- print "The project map is updated: ", ProjectMapPath
# TODO: Add an option not to build.
@@ -65,7 +68,13 @@ def addNewProject(ID) :
if __name__ == '__main__':
if len(sys.argv) < 2:
print >> sys.stderr, 'Usage: ', sys.argv[0],\
- '[project ID]'
+ 'project_ID <mode>' \
+ 'mode - 0 for single file project; 1 for scan_build'
sys.exit(-1)
+
+ IsScanBuild = 1
+ if (len(sys.argv) >= 3):
+ IsScanBuild = int(sys.argv[2])
+ assert((IsScanBuild == 0) | (IsScanBuild == 1))
- addNewProject(sys.argv[1])
+ addNewProject(sys.argv[1], IsScanBuild)
diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py
index c2209cc93cfc..3fccb9ac1ef1 100644
--- a/utils/analyzer/SATestBuild.py
+++ b/utils/analyzer/SATestBuild.py
@@ -29,7 +29,7 @@ The files which should be kept around for failure investigations:
Assumptions (TODO: shouldn't need to assume these.):
The script is being run from the Repository Directory.
- The compiler for scan-build is in the PATH.
+ The compiler for scan-build and scan-build are in the PATH.
export PATH=/Users/zaks/workspace/c2llvm/build/Release+Asserts/bin:$PATH
For more logging, set the env variables:
@@ -45,18 +45,19 @@ import glob
import shutil
import time
import plistlib
-from subprocess import check_call
+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.
-PreprocessScript = "pre_run_static_analyzer.sh"
+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.
@@ -69,8 +70,24 @@ DiffsSummaryFileName = "diffs.txt"
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,cplusplus,security,unix,osx,cocoa"
+
Verbose = 1
+IsReferenceBuild = False
+
+# Make sure we flush the output after every print statement.
+class flushfile(object):
+ def __init__(self, f):
+ self.f = f
+ def write(self, x):
+ self.f.write(x)
+ self.f.flush()
+
+sys.stdout = flushfile(sys.stdout)
+
def getProjectMapPath():
ProjectMapPath = os.path.join(os.path.abspath(os.curdir),
ProjectMapFile)
@@ -83,9 +100,15 @@ def getProjectMapPath():
def getProjectDir(ID):
return os.path.join(os.path.abspath(os.curdir), ID)
+def getSBOutputDirName() :
+ if IsReferenceBuild == True :
+ return SBOutputDirReferencePrefix + SBOutputDirName
+ else :
+ return SBOutputDirName
+
# Run pre-processing script if any.
-def runPreProcessingScript(Dir, PBuildLogFile):
- ScriptPath = os.path.join(Dir, PreprocessScript)
+def runCleanupScript(Dir, PBuildLogFile):
+ ScriptPath = os.path.join(Dir, CleanupScript)
if os.path.exists(ScriptPath):
try:
if Verbose == 1:
@@ -109,8 +132,8 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
if not os.path.exists(BuildScriptPath):
print "Error: build script is not defined: %s" % BuildScriptPath
sys.exit(-1)
- SBOptions = "-plist -o " + SBOutputDir + " "
- SBOptions += "-enable-checker core,deadcode.DeadStores"
+ SBOptions = "-plist-html -o " + SBOutputDir + " "
+ SBOptions += "-enable-checker " + Checkers + " "
try:
SBCommandFile = open(BuildScriptPath, "r")
SBPrefix = "scan-build " + SBOptions + " "
@@ -124,34 +147,107 @@ def runScanBuild(Dir, SBOutputDir, PBuildLogFile):
except:
print "Error: scan-build failed. See ",PBuildLogFile.name,\
" for details."
- sys.exit(-1)
+ raise
+
+def hasNoExtension(FileName):
+ (Root, Ext) = os.path.splitext(FileName)
+ if ((Ext == "")) :
+ return True
+ return False
+
+def isValidSingleInputFile(FileName):
+ (Root, Ext) = os.path.splitext(FileName)
+ if ((Ext == ".i") | (Ext == ".ii") |
+ (Ext == ".c") | (Ext == ".cpp") |
+ (Ext == ".m") | (Ext == "")) :
+ return True
+ return False
+
+# Run analysis on a set of preprocessed files.
+def runAnalyzePreprocessed(Dir, SBOutputDir):
+ 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 += "-analyzer-checker=" + Checkers +" -fcxx-exceptions -fblocks "
+
+ PlistPath = os.path.join(Dir, SBOutputDir, "date")
+ FailPath = os.path.join(PlistPath, "failures");
+ os.makedirs(FailPath);
+
+ for FullFileName in glob.glob(Dir + "/*"):
+ FileName = os.path.basename(FullFileName)
+ Failed = False
+
+ # Only run the analyzes on supported files.
+ if (hasNoExtension(FileName)):
+ continue
+ if (isValidSingleInputFile(FileName) == False):
+ print "Error: Invalid single input file %s." % (FullFileName,)
+ raise Exception()
+
+ # Build and call the analyzer command.
+ OutputOption = "-o " + os.path.join(PlistPath, FileName) + ".plist "
+ Command = CmdPrefix + OutputOption + os.path.join(Dir, FileName)
+ LogFile = open(os.path.join(FailPath, FileName + ".stderr.txt"), "w+b")
+ try:
+ if Verbose == 1:
+ print " Executing: %s" % (Command,)
+ check_call(Command, cwd = Dir, stderr=LogFile,
+ stdout=LogFile,
+ shell=True)
+ except CalledProcessError, e:
+ print "Error: Analyzes of %s failed. See %s for details." \
+ "Error code %d." % \
+ (FullFileName, LogFile.name, e.returncode)
+ Failed = True
+ finally:
+ LogFile.close()
+
+ # If command did not fail, erase the log file.
+ if Failed == False:
+ os.remove(LogFile.name);
-def buildProject(Dir, SBOutputDir):
+def buildProject(Dir, SBOutputDir, IsScanBuild):
TBegin = time.time()
- BuildLogPath = os.path.join(Dir, BuildLogName)
+ BuildLogPath = os.path.join(SBOutputDir, LogFolderName, BuildLogName)
print "Log file: %s" % (BuildLogPath,)
-
+ print "Output directory: %s" %(SBOutputDir, )
+
# Clean up the log file.
if (os.path.exists(BuildLogPath)) :
RmCommand = "rm " + BuildLogPath
if Verbose == 1:
- print " Executing: %s." % (RmCommand,)
+ print " Executing: %s" % (RmCommand,)
check_call(RmCommand, shell=True)
+
+ # Clean up scan build results.
+ if (os.path.exists(SBOutputDir)) :
+ RmCommand = "rm -r " + SBOutputDir
+ if Verbose == 1:
+ print " Executing: %s" % (RmCommand,)
+ check_call(RmCommand, shell=True)
+ assert(not os.path.exists(SBOutputDir))
+ os.makedirs(os.path.join(SBOutputDir, LogFolderName))
# Open the log file.
PBuildLogFile = open(BuildLogPath, "wb+")
- try:
- # Clean up scan build results.
- if (os.path.exists(SBOutputDir)) :
- RmCommand = "rm -r " + SBOutputDir
- if Verbose == 1:
- print " Executing: %s" % (RmCommand,)
- check_call(RmCommand, stderr=PBuildLogFile,
- stdout=PBuildLogFile, shell=True)
- runPreProcessingScript(Dir, PBuildLogFile)
- runScanBuild(Dir, SBOutputDir, PBuildLogFile)
+ # Build and analyze the project.
+ try:
+ runCleanupScript(Dir, PBuildLogFile)
+
+ if IsScanBuild:
+ runScanBuild(Dir, SBOutputDir, PBuildLogFile)
+ else:
+ runAnalyzePreprocessed(Dir, SBOutputDir)
+
+ if IsReferenceBuild :
+ runCleanupScript(Dir, PBuildLogFile)
+
finally:
PBuildLogFile.close()
@@ -185,9 +281,9 @@ def checkBuild(SBOutputDir):
return;
# Create summary file to display when the build fails.
- SummaryPath = os.path.join(SBOutputDir, FailuresSummaryFileName);
+ SummaryPath = os.path.join(SBOutputDir, LogFolderName, FailuresSummaryFileName)
if (Verbose > 0):
- print " Creating the failures summary file %s." % (SummaryPath,)
+ print " Creating the failures summary file %s" % (SummaryPath,)
SummaryLog = open(SummaryPath, "w+")
try:
@@ -212,8 +308,7 @@ def checkBuild(SBOutputDir):
finally:
SummaryLog.close()
- print "Error: Scan-build failed. See ", \
- os.path.join(SBOutputDir, FailuresSummaryFileName)
+ print "Error: analysis failed. See ", SummaryPath
sys.exit(-1)
# Auxiliary object to discard stdout.
@@ -231,6 +326,11 @@ def runCmpResults(Dir):
# We have to go one level down the directory tree.
RefList = glob.glob(RefDir + "/*")
NewList = glob.glob(NewDir + "/*")
+
+ # Log folders are also located in the results dir, so ignore them.
+ RefList.remove(os.path.join(RefDir, LogFolderName))
+ NewList.remove(os.path.join(NewDir, LogFolderName))
+
if len(RefList) == 0 or len(NewList) == 0:
return False
assert(len(RefList) == len(NewList))
@@ -243,7 +343,7 @@ def runCmpResults(Dir):
NewList.sort()
# Iterate and find the differences.
- HaveDiffs = False
+ NumDiffs = 0
PairList = zip(RefList, NewList)
for P in PairList:
RefDir = P[0]
@@ -259,16 +359,47 @@ def runCmpResults(Dir):
OLD_STDOUT = sys.stdout
sys.stdout = Discarder()
# Scan the results, delete empty plist files.
- HaveDiffs = CmpRuns.cmpScanBuildResults(RefDir, NewDir, Opts, False)
+ NumDiffs = CmpRuns.cmpScanBuildResults(RefDir, NewDir, Opts, False)
sys.stdout = OLD_STDOUT
- if HaveDiffs:
- print "Warning: difference in diagnostics. See %s" % (DiffsPath,)
- HaveDiffs=True
+ if (NumDiffs > 0) :
+ print "Warning: %r differences in diagnostics. See %s" % \
+ (NumDiffs, DiffsPath,)
print "Diagnostic comparison complete (time: %.2f)." % (time.time()-TBegin)
- return HaveDiffs
+ return (NumDiffs > 0)
+
+def updateSVN(Mode, ProjectsMap):
+ try:
+ ProjectsMap.seek(0)
+ for I in csv.reader(ProjectsMap):
+ ProjName = I[0]
+ Path = os.path.join(ProjName, getSBOutputDirName())
+
+ if Mode == "delete":
+ Command = "svn delete %s" % (Path,)
+ else:
+ Command = "svn add %s" % (Path,)
+
+ if Verbose == 1:
+ print " Executing: %s" % (Command,)
+ check_call(Command, shell=True)
+
+ if Mode == "delete":
+ CommitCommand = "svn commit -m \"[analyzer tests] Remove " \
+ "reference results.\""
+ else:
+ CommitCommand = "svn commit -m \"[analyzer tests] Add new " \
+ "reference results.\""
+ if Verbose == 1:
+ print " Executing: %s" % (CommitCommand,)
+ check_call(CommitCommand, shell=True)
+ except:
+ print "Error: SVN update failed."
+ sys.exit(-1)
+
+def testProject(ID, IsScanBuild, Dir=None):
+ print " \n\n--- Building project %s" % (ID,)
-def testProject(ID, IsReferenceBuild, Dir=None):
TBegin = time.time()
if Dir is None :
@@ -277,13 +408,10 @@ def testProject(ID, IsReferenceBuild, Dir=None):
print " Build directory: %s." % (Dir,)
# Set the build results directory.
- if IsReferenceBuild == True :
- SBOutputDir = os.path.join(Dir, SBOutputDirReferencePrefix + \
- SBOutputDirName)
- else :
- SBOutputDir = os.path.join(Dir, SBOutputDirName)
-
- buildProject(Dir, SBOutputDir)
+ RelOutputDir = getSBOutputDirName()
+ SBOutputDir = os.path.join(Dir, RelOutputDir)
+
+ buildProject(Dir, SBOutputDir, IsScanBuild)
checkBuild(SBOutputDir)
@@ -293,15 +421,55 @@ def testProject(ID, IsReferenceBuild, Dir=None):
print "Completed tests for project %s (time: %.2f)." % \
(ID, (time.time()-TBegin))
-def testAll(IsReferenceBuild=False):
+def testAll(InIsReferenceBuild = False, UpdateSVN = False):
+ global IsReferenceBuild
+ IsReferenceBuild = InIsReferenceBuild
+
PMapFile = open(getProjectMapPath(), "rb")
- try:
- PMapReader = csv.reader(PMapFile)
- for I in PMapReader:
- print " --- Building project %s" % (I[0],)
- testProject(I[0], IsReferenceBuild)
+ try:
+ # Validate the input.
+ for I in csv.reader(PMapFile):
+ 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."
+ raise Exception()
+
+ # When we are regenerating the reference results, we might need to
+ # update svn. Remove reference results from SVN.
+ if UpdateSVN == True:
+ assert(InIsReferenceBuild == True);
+ updateSVN("delete", PMapFile);
+
+ # Test the projects.
+ PMapFile.seek(0)
+ for I in csv.reader(PMapFile):
+ testProject(I[0], int(I[1]))
+
+ # Add reference results to SVN.
+ if UpdateSVN == True:
+ updateSVN("add", PMapFile);
+
+ except:
+ print "Error occurred. Premature termination."
+ raise
finally:
PMapFile.close()
if __name__ == '__main__':
- testAll()
+ IsReference = False
+ UpdateSVN = False
+ if len(sys.argv) >= 2:
+ if sys.argv[1] == "-r":
+ IsReference = True
+ elif sys.argv[1] == "-rs":
+ IsReference = True
+ UpdateSVN = True
+ else:
+ print >> sys.stderr, 'Usage: ', sys.argv[0],\
+ '[-r|-rs]' \
+ 'Use -r to regenerate reference output' \
+ 'Use -rs to regenerate reference output and update svn'
+
+ testAll(IsReference, UpdateSVN)
diff --git a/utils/clangVisualizers.txt b/utils/clangVisualizers.txt
index f9f834b76c50..0fef65f4ed3e 100644
--- a/utils/clangVisualizers.txt
+++ b/utils/clangVisualizers.txt
@@ -41,4 +41,94 @@ llvm::StringRef{
clang::Token{
preview((clang::tok::TokenKind)(int)$e.Kind)
-} \ No newline at end of file
+}
+
+llvm::PointerIntPair<*,*,*,*>{
+ preview (
+ #(
+ ($T1*)($e.Value & $e.PointerBitMask),
+ " [",
+ ($T3)(($e.Value >> $e.IntShift) & $e.IntMask),
+ "]"
+ )
+ )
+
+ children (
+ #(
+ #([ptr] : ($T1*)($e.Value & $e.PointerBitMask)),
+ #([int] : ($T3)($e.Value >> $e.IntShift) & $e.IntMask)
+ )
+ )
+}
+
+llvm::PointerUnion<*,*>{
+ preview (
+ #if ((($e.Val.Value >> $e.Val.IntShift) & $e.Val.IntMask) == 0) (
+ "PT1"
+ ) #else (
+ "PT2"
+ )
+ )
+
+ children (
+ #(
+ #if ((($e.Val.Value >> $e.Val.IntShift) & $e.Val.IntMask) == 0) (
+ #([ptr] : ($T1)($e.Val.Value & $e.Val.PointerBitMask))
+ ) #else (
+ #([ptr] : ($T2)($e.Val.Value & $e.Val.PointerBitMask))
+ )
+ )
+ )
+}
+
+llvm::PointerUnion3<*,*,*>{
+ preview (
+ #if (($e.Val.Val.Value & 0x2) == 2) (
+ "PT2"
+ ) #elif (($e.Val.Val.Value & 0x1) == 1) (
+ "PT3"
+ ) #else (
+ "PT1"
+ )
+ )
+
+ children (
+ #(
+ #if (($e.Val.Val.Value & 0x2) == 2) (
+ #([ptr] : ($T2)(($e.Val.Val.Value >> 2) << 2))
+ ) #elif (($e.Val.Val.Value & 0x1) == 1) (
+ #([ptr] : ($T3)(($e.Val.Val.Value >> 2) << 2))
+ ) #else (
+ #([ptr] : ($T1)(($e.Val.Val.Value >> 2) << 2))
+ )
+ )
+ )
+}
+
+llvm::PointerUnion4<*,*,*,*>{
+ preview (
+ #if (($e.Val.Val.Value & 0x3) == 3) (
+ "PT4"
+ ) #elif (($e.Val.Val.Value & 0x2) == 2) (
+ "PT2"
+ ) #elif (($e.Val.Val.Value & 0x1) == 1) (
+ "PT3"
+ ) #else (
+ "PT1"
+ )
+ )
+
+ children (
+ #(
+ #if (($e.Val.Val.Value & 0x3) == 3) (
+ #([ptr] : ($T4)(($e.Val.Val.Value >> 2) << 2))
+ ) #elif (($e.Val.Val.Value & 0x2) == 2) (
+ #([ptr] : ($T2)(($e.Val.Val.Value >> 2) << 2))
+ ) #elif (($e.Val.Val.Value & 0x1) == 1) (
+ #([ptr] : ($T3)(($e.Val.Val.Value >> 2) << 2))
+ ) #else (
+ #([ptr] : ($T1)(($e.Val.Val.Value >> 2) << 2))
+ )
+ )
+ )
+}
diff --git a/utils/find-unused-diagnostics.sh b/utils/find-unused-diagnostics.sh
new file mode 100644
index 000000000000..89b7f7a700d5
--- /dev/null
+++ b/utils/find-unused-diagnostics.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# This script produces a list of all diagnostics that are defined
+# in Diagnostic*.td files but not used in sources.
+#
+
+ALL_DIAGS=$(mktemp)
+ALL_SOURCES=$(mktemp)
+
+grep -E --only-matching --no-filename '(err_|warn_|ext_|note_)[a-z_]+ ' ./include/clang/Basic/Diagnostic*.td > $ALL_DIAGS
+find lib include tools -name \*.cpp -or -name \*.h > $ALL_SOURCES
+for DIAG in $(cat $ALL_DIAGS); do
+ if ! grep -r $DIAG $(cat $ALL_SOURCES) > /dev/null; then
+ echo $DIAG
+ fi;
+done
+
+rm $ALL_DIAGS $ALL_SOURCES
+