diff options
Diffstat (limited to 'gnu/llvm/utils/FileCheck/FileCheck.cpp')
| -rw-r--r-- | gnu/llvm/utils/FileCheck/FileCheck.cpp | 83 |
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; } |
