Allow multiple check prefixes in FileCheck.

This is useful if you want to run multiple variations
of a single test, and the majority of check lines
should be the same.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@194343 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Matt Arsenault 2013-11-10 02:04:09 +00:00
parent 432bdf6571
commit ee4f5eae1c
15 changed files with 353 additions and 87 deletions

View File

@ -30,11 +30,13 @@ OPTIONS
.. option:: --check-prefix prefix
FileCheck searches the contents of ``match-filename`` for patterns to match.
By default, these patterns are prefixed with "``CHECK:``". If you'd like to
use a different prefix (e.g. because the same input file is checking multiple
different tool or options), the :option:`--check-prefix` argument allows you
to specify a specific prefix to match.
FileCheck searches the contents of ``match-filename`` for patterns to
match. By default, these patterns are prefixed with "``CHECK:``".
If you'd like to use a different prefix (e.g. because the same input
file is checking multiple different tool or options), the
:option:`--check-prefix` argument allows you to specify one or more
prefixes to match. Multiple prefixes are useful for tests which might
change for different run options, but most lines remain the same.
.. option:: --input-file filename

View File

@ -0,0 +1,5 @@
; RUN: FileCheck -check-prefix=A -check-prefix=B -input-file %s %s
this is the string to be matched
; B-DAG: this is the string to be {{matched}}

View File

@ -0,0 +1,5 @@
; RUN: FileCheck -check-prefix=B -check-prefix=A -input-file %s %s
this is the string to be matched
; B-DAG: this is the string to be {{matched}}

View File

@ -0,0 +1,7 @@
; RUN: FileCheck -check-prefix=A -input-file %s %s
this should be matched
; B-DAG: foo
; A-DAG: {{this}} should be matched

View File

@ -0,0 +1,27 @@
; RUN: FileCheck -check-prefix=A -check-prefix=B -input-file %s %s
add r10, r1, r2
add r11, r3, r4
mul r5, r10, r11
mul r11, r3, r4
mul r10, r1, r2
add r5, r10, r11
add r11, r3, r4
add r10, r1, r2
mul r5, r10, r11
; B-DAG: add [[REG1:r[0-9]+]], r1, r2
; B-DAG: add [[REG2:r[0-9]+]], r3, r4
; B: mul r5, [[REG1]], [[REG2]]
; A-DAG: mul [[REG1:r[0-9]+]], r1, r2
; A-DAG: mul [[REG2:r[0-9]+]], r3, r4
; A: add r5, [[REG1]], [[REG2]]
; B-DAG: add [[REG1:r[0-9]+]], r1, r2
; B-DAG: add [[REG2:r[0-9]+]], r3, r4
; B-NOT: xor
; B-DAG: mul r5, [[REG1]], [[REG2]]

View File

@ -0,0 +1,7 @@
; RUN: not FileCheck -check-prefix=A -check-prefix=AA -input-file %s %s
this is the string to be matched
this should also be matched
; BAA-DAG: this is the string to be {{matched}}
; BAA-DAG: this should also be {{matched}}

View File

@ -0,0 +1,6 @@
// RUN: FileCheck -check-prefix=ONE -check-prefix=TWO -input-file %s %s
foo
bar
; ONE-LABEL: {{f}}oo
; TWO-NEXT: {{b}}ar

View File

@ -0,0 +1,10 @@
// RUN: FileCheck -check-prefix=B -check-prefix=BOTH -input-file %s %s
// RUN: FileCheck -check-prefix=A -check-prefix=BOTH -input-file %s %s
; A: {{a}}aaaaa
; B: {{b}}bbbb
; BOTH: {{q}}qqqqq
aaaaaa
bbbbb
qqqqqq
ccccc

View File

@ -0,0 +1,11 @@
; RUN: FileCheck -check-prefix=FOO -check-prefix=FOOBAR -check-prefix=BARFOO -input-file %s %s
; RUN: FileCheck -check-prefix=FOOBAR -check-prefix=FOO -check-prefix=BARFOO -input-file %s %s
; RUN: FileCheck -check-prefix=FOOBAR -check-prefix=BARFOO -check-prefix=FOO -input-file %s %s
this is the match
this is another
FOO
FOOBAR
FOOBAR: this is the {{match}}
BARFOO: this is {{another}}

View File

@ -0,0 +1,9 @@
// RUN: FileCheck -check-prefix=AAAOVERLAP -check-prefix=OVERLAP -input-file %s %s
foo
bar
buzz
OVERLAP: foo
AAAOVERLAP: bar
OVERLAP: buzz

View File

@ -0,0 +1,2 @@
RUN: FileCheck -check-prefix=RUN -input-file %s %s
// Prefix is at the first character in the file. The run line then matches itself.

View File

@ -0,0 +1,9 @@
// RUN: FileCheck -check-prefix=ANOTHER-PREFIX -input-file %s %s
// RUN: not FileCheck -check-prefix=PREFIX1 -check-prefix=PREFIX2 -input-file %s %s 2>&1 | FileCheck -strict-whitespace -check-prefix=CHECK-NONEXISTENT-PREFIX -check-prefix=ALSO-NONEXISTENT %s
foobar
; ANOTHER-PREFIX: foobar
; We use regex to match the colon so that FileCheck won't think it is a check
; prefix.
; CHECK-NONEXISTENT-PREFIX: error: no check strings found with prefixes 'PREFIX1{{:}}', 'PREFIX2{{:}}'

View File

@ -0,0 +1,7 @@
// RUN: not FileCheck -check-prefix=SOMEPREFIX -input-file %s %s
// RUN: FileCheck -check-prefix=ANOTHER -input-file %s %s
asdf
; SOMEPREFIX: {{t}}his_is_not_asdf
; ANOTHER: {{a}}sdf

View File

@ -1,7 +1,9 @@
// RUN: not FileCheck -check-prefix=A! -input-file %s %s 2>&1 | FileCheck -check-prefix=BAD_PREFIX %s
// RUN: FileCheck -check-prefix=A1a-B_c -input-file %s %s
// RUN: not FileCheck -check-prefix=REPEAT -check-prefix=REPEAT -input-file %s %s 2>&1 | FileCheck -check-prefix=BAD_PREFIX %s
// RUN: not FileCheck -check-prefix=VALID -check-prefix=A! -input-file %s %s 2>&1 | FileCheck -check-prefix=BAD_PREFIX %s
foobar
; A1a-B_c: foobar
; BAD_PREFIX: Supplied check-prefix is invalid! Prefixes must start with a letter and contain only alphanumeric characters, hyphens and underscores
; BAD_PREFIX: Supplied check-prefix is invalid! Prefixes must be
unique and start with a letter and contain only alphanumeric characters, hyphens and underscores

View File

@ -20,6 +20,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
@ -42,14 +43,16 @@ static cl::opt<std::string>
InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
cl::init("-"), cl::value_desc("filename"));
static cl::opt<std::string>
CheckPrefix("check-prefix", cl::init("CHECK"),
cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
static cl::list<std::string>
CheckPrefixes("check-prefix",
cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
static cl::opt<bool>
NoCanonicalizeWhiteSpace("strict-whitespace",
cl::desc("Do not treat all horizontal whitespace as equivalent"));
typedef cl::list<std::string>::const_iterator prefix_iterator;
//===----------------------------------------------------------------------===//
// Pattern Handling Code.
//===----------------------------------------------------------------------===//
@ -103,11 +106,15 @@ public:
/// getLoc - Return the location in source code.
SMLoc getLoc() const { return PatternLoc; }
/// ParsePattern - Parse the given string into the Pattern. SM provides the
/// SourceMgr used for error reports, and LineNumber is the line number in
/// the input file from which the pattern string was read.
/// Returns true in case of an error, false otherwise.
bool ParsePattern(StringRef PatternStr, SourceMgr &SM, unsigned LineNumber);
/// ParsePattern - Parse the given string into the Pattern. Prefix provides
/// which prefix is being matched, SM provides the SourceMgr used for error
/// reports, and LineNumber is the line number in the input file from which
/// the pattern string was read. Returns true in case of an error, false
/// otherwise.
bool ParsePattern(StringRef PatternStr,
StringRef Prefix,
SourceMgr &SM,
unsigned LineNumber);
/// Match - Match the pattern string against the input buffer Buffer. This
/// returns the position that is matched or npos if there is no match. If
@ -152,7 +159,9 @@ private:
};
bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM,
bool Pattern::ParsePattern(StringRef PatternStr,
StringRef Prefix,
SourceMgr &SM,
unsigned LineNumber) {
this->LineNumber = LineNumber;
PatternLoc = SMLoc::getFromPointer(PatternStr.data());
@ -166,7 +175,7 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM,
if (PatternStr.empty()) {
SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
"found empty check string with prefix '" +
CheckPrefix+":'");
Prefix + ":'");
return true;
}
@ -594,6 +603,9 @@ struct CheckString {
/// Pat - The pattern to match.
Pattern Pat;
/// Prefix - Which prefix name this check matched.
StringRef Prefix;
/// Loc - The location in the match file that the check string was specified.
SMLoc Loc;
@ -606,8 +618,12 @@ struct CheckString {
/// file).
std::vector<Pattern> DagNotStrings;
CheckString(const Pattern &P, SMLoc L, Check::CheckType Ty)
: Pat(P), Loc(L), CheckTy(Ty) {}
CheckString(const Pattern &P,
StringRef S,
SMLoc L,
Check::CheckType Ty)
: Pat(P), Prefix(S), Loc(L), CheckTy(Ty) {}
/// Check - Match check string and its "not strings" and/or "dag strings".
size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
@ -670,43 +686,155 @@ static bool IsPartOfWord(char c) {
return (isalnum(c) || c == '-' || c == '_');
}
static Check::CheckType FindCheckType(StringRef &Buffer, StringRef Prefix) {
// Get the size of the prefix extension.
static size_t CheckTypeSize(Check::CheckType Ty) {
switch (Ty) {
case Check::CheckNone:
return 0;
case Check::CheckPlain:
return sizeof(":") - 1;
case Check::CheckNext:
return sizeof("-NEXT:") - 1;
case Check::CheckNot:
return sizeof("-NOT:") - 1;
case Check::CheckDAG:
return sizeof("-DAG:") - 1;
case Check::CheckLabel:
return sizeof("-LABEL:") - 1;
case Check::CheckEOF:
llvm_unreachable("Should not be using EOF size");
}
llvm_unreachable("Bad check type");
}
static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
char NextChar = Buffer[Prefix.size()];
// Verify that the : is present after the prefix.
if (NextChar == ':') {
Buffer = Buffer.substr(Prefix.size() + 1);
if (NextChar == ':')
return Check::CheckPlain;
}
if (NextChar != '-') {
Buffer = Buffer.drop_front(1);
if (NextChar != '-')
return Check::CheckNone;
}
StringRef Rest = Buffer.drop_front(Prefix.size() + 1);
if (Rest.startswith("NEXT:")) {
Buffer = Rest.drop_front(sizeof("NEXT:") - 1);
if (Rest.startswith("NEXT:"))
return Check::CheckNext;
}
if (Rest.startswith("NOT:")) {
Buffer = Rest.drop_front(sizeof("NOT:") - 1);
if (Rest.startswith("NOT:"))
return Check::CheckNot;
}
if (Rest.startswith("DAG:")) {
Buffer = Rest.drop_front(sizeof("DAG:") - 1);
if (Rest.startswith("DAG:"))
return Check::CheckDAG;
}
if (Rest.startswith("LABEL:")) {
Buffer = Rest.drop_front(sizeof("LABEL:") - 1);
if (Rest.startswith("LABEL:"))
return Check::CheckLabel;
return Check::CheckNone;
}
// From the given position, find the next character after the word.
static size_t SkipWord(StringRef Str, size_t Loc) {
while (Loc < Str.size() && IsPartOfWord(Str[Loc]))
++Loc;
return Loc;
}
// Try to find the first match in buffer for any prefix. If a valid match is
// found, return that prefix and set its type and location. If there are almost
// matches (e.g. the actual prefix string is found, but is not an actual check
// string), but no valid match, return an empty string and set the position to
// resume searching from. If no partial matches are found, return an empty
// string and the location will be StringRef::npos. If one prefix is a substring
// of another, the maximal match should be found. e.g. if "A" and "AA" are
// prefixes then AA-CHECK: should match the second one.
static StringRef FindFirstCandidateMatch(StringRef &Buffer,
Check::CheckType &CheckTy,
size_t &CheckLoc) {
StringRef FirstPrefix;
size_t FirstLoc = StringRef::npos;
size_t SearchLoc = StringRef::npos;
Check::CheckType FirstTy = Check::CheckNone;
CheckTy = Check::CheckNone;
CheckLoc = StringRef::npos;
for (prefix_iterator I = CheckPrefixes.begin(), E = CheckPrefixes.end();
I != E; ++I) {
StringRef Prefix(*I);
size_t PrefixLoc = Buffer.find(Prefix);
if (PrefixLoc == StringRef::npos)
continue;
// Track where we are searching for invalid prefixes that look almost right.
// We need to only advance to the first partial match on the next attempt
// since a partial match could be a substring of a later, valid prefix.
// Need to skip to the end of the word, otherwise we could end up
// matching a prefix in a substring later.
if (PrefixLoc < SearchLoc)
SearchLoc = SkipWord(Buffer, PrefixLoc);
// We only want to find the first match to avoid skipping some.
if (PrefixLoc > FirstLoc)
continue;
StringRef Rest = Buffer.drop_front(PrefixLoc);
// Make sure we have actually found the prefix, and not a word containing
// it. This should also prevent matching the wrong prefix when one is a
// substring of another.
if (PrefixLoc != 0 && IsPartOfWord(Buffer[PrefixLoc - 1]))
continue;
Check::CheckType Ty = FindCheckType(Rest, Prefix);
if (Ty == Check::CheckNone)
continue;
FirstLoc = PrefixLoc;
FirstTy = Ty;
FirstPrefix = Prefix;
}
Buffer = Buffer.drop_front(1);
return Check::CheckNone;
if (FirstPrefix.empty()) {
CheckLoc = SearchLoc;
} else {
CheckTy = FirstTy;
CheckLoc = FirstLoc;
}
return FirstPrefix;
}
static StringRef FindFirstMatchingPrefix(StringRef &Buffer,
unsigned &LineNumber,
Check::CheckType &CheckTy,
size_t &CheckLoc) {
while (!Buffer.empty()) {
StringRef Prefix = FindFirstCandidateMatch(Buffer, CheckTy, CheckLoc);
// If we found a real match, we are done.
if (!Prefix.empty()) {
LineNumber += Buffer.substr(0, CheckLoc).count('\n');
return Prefix;
}
// We didn't find any almost matches either, we are also done.
if (CheckLoc == StringRef::npos)
return StringRef();
LineNumber += Buffer.substr(0, CheckLoc + 1).count('\n');
// Advance to the last possible match we found and try again.
Buffer = Buffer.drop_front(CheckLoc + 1);
}
return StringRef();
}
/// ReadCheckFile - Read the check file, which specifies the sequence of
@ -738,32 +866,24 @@ static bool ReadCheckFile(SourceMgr &SM,
unsigned LineNumber = 1;
while (1) {
// See if Prefix occurs in the memory buffer.
size_t PrefixLoc = Buffer.find(CheckPrefix);
// If we didn't find a match, we're done.
if (PrefixLoc == StringRef::npos)
Check::CheckType CheckTy;
size_t PrefixLoc;
// See if a prefix occurs in the memory buffer.
StringRef UsedPrefix = FindFirstMatchingPrefix(Buffer,
LineNumber,
CheckTy,
PrefixLoc);
if (UsedPrefix.empty())
break;
LineNumber += Buffer.substr(0, PrefixLoc).count('\n');
Buffer = Buffer.drop_front(PrefixLoc);
// Keep the charcter before our prefix so we can validate that we have
// found our prefix, and account for cases when PrefixLoc is 0.
Buffer = Buffer.substr(std::min(PrefixLoc-1, PrefixLoc));
// Location to use for error messages.
const char *UsedPrefixStart = Buffer.data() + (PrefixLoc == 0 ? 0 : 1);
const char *CheckPrefixStart = Buffer.data() + (PrefixLoc == 0 ? 0 : 1);
// Make sure we have actually found our prefix, and not a word containing
// our prefix.
if (PrefixLoc != 0 && IsPartOfWord(Buffer[0])) {
Buffer = Buffer.substr(CheckPrefix.size());
continue;
}
// When we find a check prefix, keep track of what kind of type of CHECK we
// have.
Check::CheckType CheckTy = FindCheckType(Buffer, CheckPrefix);
if (CheckTy == Check::CheckNone)
continue;
// PrefixLoc is to the start of the prefix. Skip to the end.
Buffer = Buffer.drop_front(UsedPrefix.size() + CheckTypeSize(CheckTy));
// Okay, we found the prefix, yay. Remember the rest of the line, but ignore
// leading and trailing whitespace.
@ -777,15 +897,15 @@ static bool ReadCheckFile(SourceMgr &SM,
// Parse the pattern.
Pattern P(CheckTy);
if (P.ParsePattern(Buffer.substr(0, EOL), SM, LineNumber))
if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber))
return true;
// Verify that CHECK-LABEL lines do not define or use variables
if ((CheckTy == Check::CheckLabel) && P.hasVariable()) {
SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
SourceMgr::DK_Error,
"found '"+CheckPrefix+"-LABEL:' with variable definition"
" or use");
"found '" + UsedPrefix + "-LABEL:'"
" with variable definition or use");
return true;
}
@ -793,10 +913,10 @@ static bool ReadCheckFile(SourceMgr &SM,
// Verify that CHECK-NEXT lines have at least one CHECK line before them.
if ((CheckTy == Check::CheckNext) && CheckStrings.empty()) {
SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
SourceMgr::DK_Error,
"found '"+CheckPrefix+"-NEXT:' without previous '"+
CheckPrefix+ ": line");
"found '" + UsedPrefix + "-NEXT:' without previous '"
+ UsedPrefix + ": line");
return true;
}
@ -808,22 +928,33 @@ static bool ReadCheckFile(SourceMgr &SM,
// Okay, add the string we captured to the output vector and move on.
CheckStrings.push_back(CheckString(P,
UsedPrefix,
PatternLoc,
CheckTy));
std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
}
// Add an EOF pattern for any trailing CHECK-DAG/-NOTs.
// Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
// prefix as a filler for the error message.
if (!DagNotMatches.empty()) {
CheckStrings.push_back(CheckString(Pattern(Check::CheckEOF),
CheckPrefixes[0],
SMLoc::getFromPointer(Buffer.data()),
Check::CheckEOF));
std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
}
if (CheckStrings.empty()) {
errs() << "error: no check strings found with prefix '" << CheckPrefix
<< ":'\n";
errs() << "error: no check strings found with prefix"
<< (CheckPrefixes.size() > 1 ? "es " : " ");
for (size_t I = 0, N = CheckPrefixes.size(); I != N; ++I) {
StringRef Prefix(CheckPrefixes[I]);
errs() << '\'' << Prefix << ":'";
if (I != N - 1)
errs() << ", ";
}
errs() << '\n';
return true;
}
@ -933,7 +1064,7 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
unsigned NumNewLines = CountNumNewlinesBetween(Buffer);
if (NumNewLines == 0) {
SM.PrintMessage(Loc, SourceMgr::DK_Error, CheckPrefix+
SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix +
"-NEXT: is on the same line as previous match");
SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()),
SourceMgr::DK_Note, "'next' match was here");
@ -943,7 +1074,7 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
}
if (NumNewLines != 1) {
SM.PrintMessage(Loc, SourceMgr::DK_Error, CheckPrefix+
SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix +
"-NEXT: is not on the line after the previous match");
SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()),
SourceMgr::DK_Note, "'next' match was here");
@ -970,9 +1101,9 @@ bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()+Pos),
SourceMgr::DK_Error,
CheckPrefix+"-NOT: string occurred!");
Prefix + "-NOT: string occurred!");
SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note,
CheckPrefix+"-NOT: pattern specified here");
Prefix + "-NOT: pattern specified here");
return true;
}
@ -1022,17 +1153,17 @@ size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
// Reordered?
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos),
SourceMgr::DK_Error,
CheckPrefix+"-DAG: found a match of CHECK-DAG"
Prefix + "-DAG: found a match of CHECK-DAG"
" reordering across a CHECK-NOT");
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos),
SourceMgr::DK_Note,
CheckPrefix+"-DAG: the farthest match of CHECK-DAG"
Prefix + "-DAG: the farthest match of CHECK-DAG"
" is found here");
SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note,
CheckPrefix+"-NOT: the crossed pattern specified"
Prefix + "-NOT: the crossed pattern specified"
" here");
SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note,
CheckPrefix+"-DAG: the reordered pattern specified"
Prefix + "-DAG: the reordered pattern specified"
" here");
return StringRef::npos;
}
@ -1056,10 +1187,34 @@ size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
return LastPos;
}
bool ValidateCheckPrefix() {
// The check prefix must contain only alphanumeric, hyphens and underscores.
Regex prefixValidator("^[a-zA-Z0-9_-]*$");
return prefixValidator.match(CheckPrefix);
// A check prefix must contain only alphanumeric, hyphens and underscores.
static bool ValidateCheckPrefix(StringRef CheckPrefix) {
Regex Validator("^[a-zA-Z0-9_-]*$");
return Validator.match(CheckPrefix);
}
static bool ValidateCheckPrefixes() {
StringSet<> PrefixSet;
for (prefix_iterator I = CheckPrefixes.begin(), E = CheckPrefixes.end();
I != E; ++I) {
StringRef Prefix(*I);
if (!PrefixSet.insert(Prefix))
return false;
if (!ValidateCheckPrefix(Prefix))
return false;
}
return true;
}
// I don't think there's a way to specify an initial value for cl::list,
// so if nothing was specified, add the default
static void AddCheckPrefixIfNeeded() {
if (CheckPrefixes.empty())
CheckPrefixes.push_back("CHECK");
}
int main(int argc, char **argv) {
@ -1067,13 +1222,15 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv);
cl::ParseCommandLineOptions(argc, argv);
if (!ValidateCheckPrefix()) {
errs() << "Supplied check-prefix is invalid! Prefixes must start with a "
"letter and contain only alphanumeric characters, hyphens and "
"underscores\n";
if (!ValidateCheckPrefixes()) {
errs() << "Supplied check-prefix is invalid! Prefixes must be unique and "
"start with a letter and contain only alphanumeric characters, "
"hyphens and underscores\n";
return 2;
}
AddCheckPrefixIfNeeded();
SourceMgr SM;
// Read the expected strings from the check file.