summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/utils/FileCheck/FileCheck.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/utils/FileCheck/FileCheck.cpp')
-rw-r--r--gnu/llvm/utils/FileCheck/FileCheck.cpp83
1 files changed, 64 insertions, 19 deletions
diff --git a/gnu/llvm/utils/FileCheck/FileCheck.cpp b/gnu/llvm/utils/FileCheck/FileCheck.cpp
index f73a0fee76c..6c9b62d5b24 100644
--- a/gnu/llvm/utils/FileCheck/FileCheck.cpp
+++ b/gnu/llvm/utils/FileCheck/FileCheck.cpp
@@ -45,6 +45,11 @@ InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
static cl::list<std::string>
CheckPrefixes("check-prefix",
cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
+static cl::alias CheckPrefixesAlias(
+ "check-prefixes", cl::aliasopt(CheckPrefixes), cl::CommaSeparated,
+ cl::NotHidden,
+ cl::desc(
+ "Alias for -check-prefix permitting multiple comma separated values"));
static cl::opt<bool>
NoCanonicalizeWhiteSpace("strict-whitespace",
@@ -62,6 +67,12 @@ static cl::opt<bool> AllowEmptyInput(
cl::desc("Allow the input file to be empty. This is useful when making\n"
"checks that some error message does not occur, for example."));
+static cl::opt<bool> MatchFullLines(
+ "match-full-lines", cl::init(false),
+ cl::desc("Require all positive matches to cover an entire input line.\n"
+ "Allows leading and trailing whitespace if --strict-whitespace\n"
+ "is not also passed."));
+
typedef cl::list<std::string>::const_iterator prefix_iterator;
//===----------------------------------------------------------------------===//
@@ -80,7 +91,9 @@ namespace Check {
/// MatchEOF - When set, this pattern only matches the end of file. This is
/// used for trailing CHECK-NOTs.
- CheckEOF
+ CheckEOF,
+ /// CheckBadNot - Found -NOT combined with another CHECK suffix.
+ CheckBadNot
};
}
@@ -174,6 +187,8 @@ bool Pattern::ParsePattern(StringRef PatternStr,
StringRef Prefix,
SourceMgr &SM,
unsigned LineNumber) {
+ bool MatchFullLinesHere = MatchFullLines && CheckTy != Check::CheckNot;
+
this->LineNumber = LineNumber;
PatternLoc = SMLoc::getFromPointer(PatternStr.data());
@@ -191,13 +206,19 @@ bool Pattern::ParsePattern(StringRef PatternStr,
}
// Check to see if this is a fixed string, or if it has regex pieces.
- if (PatternStr.size() < 2 ||
- (PatternStr.find("{{") == StringRef::npos &&
- PatternStr.find("[[") == StringRef::npos)) {
+ if (!MatchFullLinesHere &&
+ (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
+ PatternStr.find("[[") == StringRef::npos))) {
FixedStr = PatternStr;
return false;
}
+ if (MatchFullLinesHere) {
+ RegExStr += '^';
+ if (!NoCanonicalizeWhiteSpace)
+ RegExStr += " *";
+ }
+
// Paren value #0 is for the fully matched string. Any new parenthesized
// values add from there.
unsigned CurParen = 1;
@@ -329,6 +350,12 @@ bool Pattern::ParsePattern(StringRef PatternStr,
PatternStr = PatternStr.substr(FixedMatchEnd);
}
+ if (MatchFullLinesHere) {
+ if (!NoCanonicalizeWhiteSpace)
+ RegExStr += " *";
+ RegExStr += '$';
+ }
+
return false;
}
@@ -598,19 +625,15 @@ struct CheckString {
/// CheckTy - Specify what kind of check this is. e.g. CHECK-NEXT: directive,
/// as opposed to a CHECK: directive.
- Check::CheckType CheckTy;
+ // Check::CheckType CheckTy;
/// DagNotStrings - These are all of the strings that are disallowed from
/// occurring between this match string and the previous one (or start of
/// file).
std::vector<Pattern> DagNotStrings;
-
- CheckString(const Pattern &P,
- StringRef S,
- SMLoc L,
- Check::CheckType Ty)
- : Pat(P), Prefix(S), Loc(L), CheckTy(Ty) {}
+ CheckString(const Pattern &P, StringRef S, SMLoc L)
+ : Pat(P), Prefix(S), Loc(L) {}
/// Check - Match check string and its "not strings" and/or "dag strings".
size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
@@ -677,6 +700,7 @@ static bool IsPartOfWord(char c) {
static size_t CheckTypeSize(Check::CheckType Ty) {
switch (Ty) {
case Check::CheckNone:
+ case Check::CheckBadNot:
return 0;
case Check::CheckPlain:
@@ -730,6 +754,12 @@ static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
if (Rest.startswith("LABEL:"))
return Check::CheckLabel;
+ // You can't combine -NOT with another suffix.
+ if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||
+ Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||
+ Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:"))
+ return Check::CheckBadNot;
+
return Check::CheckNone;
}
@@ -898,6 +928,14 @@ static bool ReadCheckFile(SourceMgr &SM,
// PrefixLoc is to the start of the prefix. Skip to the end.
Buffer = Buffer.drop_front(UsedPrefix.size() + CheckTypeSize(CheckTy));
+ // Complain about useful-looking but unsupported suffixes.
+ if (CheckTy == Check::CheckBadNot) {
+ SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
+ SourceMgr::DK_Error,
+ "unsupported -NOT combo on prefix '" + UsedPrefix + "'");
+ return true;
+ }
+
// Okay, we found the prefix, yay. Remember the rest of the line, but ignore
// leading and trailing whitespace.
Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
@@ -942,7 +980,7 @@ static bool ReadCheckFile(SourceMgr &SM,
}
// Okay, add the string we captured to the output vector and move on.
- CheckStrings.emplace_back(P, UsedPrefix, PatternLoc, CheckTy);
+ CheckStrings.emplace_back(P, UsedPrefix, PatternLoc);
std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
DagNotMatches = ImplicitNegativeChecks;
}
@@ -951,8 +989,7 @@ static bool ReadCheckFile(SourceMgr &SM,
// prefix as a filler for the error message.
if (!DagNotMatches.empty()) {
CheckStrings.emplace_back(Pattern(Check::CheckEOF), *CheckPrefixes.begin(),
- SMLoc::getFromPointer(Buffer.data()),
- Check::CheckEOF);
+ SMLoc::getFromPointer(Buffer.data()));
std::swap(DagNotMatches, CheckStrings.back().DagNotStrings);
}
@@ -965,7 +1002,7 @@ static bool ReadCheckFile(SourceMgr &SM,
errs() << "\'" << *I << ":'";
++I;
}
- for (; I != E; ++I)
+ for (; I != E; ++I)
errs() << ", \'" << *I << ":'";
errs() << '\n';
@@ -1073,7 +1110,7 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
}
bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
- if (CheckTy != Check::CheckNext)
+ if (Pat.getCheckTy() != Check::CheckNext)
return false;
// Count the number of newlines between the previous match and this one.
@@ -1112,7 +1149,7 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
}
bool CheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
- if (CheckTy != Check::CheckSame)
+ if (Pat.getCheckTy() != Check::CheckSame)
return false;
// Count the number of newlines between the previous match and this one.
@@ -1266,8 +1303,15 @@ static void AddCheckPrefixIfNeeded() {
CheckPrefixes.push_back("CHECK");
}
+static void DumpCommandLine(int argc, char **argv) {
+ errs() << "FileCheck command line: ";
+ for (int I = 0; I < argc; I++)
+ errs() << " " << argv[I];
+ errs() << "\n";
+}
+
int main(int argc, char **argv) {
- sys::PrintStackTraceOnErrorSignal();
+ sys::PrintStackTraceOnErrorSignal(argv[0]);
PrettyStackTraceProgram X(argc, argv);
cl::ParseCommandLineOptions(argc, argv);
@@ -1299,6 +1343,7 @@ int main(int argc, char **argv) {
if (File->getBufferSize() == 0 && !AllowEmptyInput) {
errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
+ DumpCommandLine(argc, argv);
return 2;
}
@@ -1326,7 +1371,7 @@ int main(int argc, char **argv) {
CheckRegion = Buffer;
} else {
const CheckString &CheckLabelStr = CheckStrings[j];
- if (CheckLabelStr.CheckTy != Check::CheckLabel) {
+ if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) {
++j;
continue;
}