X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FFileCheck%2FFileCheck.cpp;h=59affa1ada1ba2b2c61d25d1593fa5f44404d1e6;hb=2991725fe2982e0fc2c28e9f53cd9a2bec90a9d9;hp=d33db18cb86323fce6ebfc7863a53c793b2c09e7;hpb=609ad7ec447f1e6beb8b51085016556cb641a83a;p=oota-llvm.git diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index d33db18cb86..59affa1ada1 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -16,7 +16,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" @@ -28,11 +27,11 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" #include #include #include #include +#include #include using namespace llvm; @@ -51,6 +50,18 @@ static cl::opt NoCanonicalizeWhiteSpace("strict-whitespace", cl::desc("Do not treat all horizontal whitespace as equivalent")); +static cl::list ImplicitCheckNot( + "implicit-check-not", + cl::desc("Add an implicit negative check with this pattern to every\n" + "positive check. This can be used to ensure that no instances of\n" + "this pattern occur which are not matched by a positive pattern"), + cl::value_desc("pattern")); + +static cl::opt AllowEmptyInput( + "allow-empty", cl::init(false), + 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.")); + typedef cl::list::const_iterator prefix_iterator; //===----------------------------------------------------------------------===// @@ -625,8 +636,9 @@ struct CheckString { /// /// \param PreserveHorizontal Don't squash consecutive horizontal whitespace /// characters to a single space. -static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB, - bool PreserveHorizontal) { +static std::unique_ptr +CanonicalizeInputFile(std::unique_ptr MB, + bool PreserveHorizontal) { SmallString<128> NewFile; NewFile.reserve(MB->getBufferSize()); @@ -651,12 +663,8 @@ static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB, ++Ptr; } - // Free the old buffer and return a new one. - MemoryBuffer *MB2 = - MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier()); - - delete MB; - return MB2; + return std::unique_ptr( + MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier())); } static bool IsPartOfWord(char c) { @@ -821,24 +829,44 @@ static StringRef FindFirstMatchingPrefix(StringRef &Buffer, /// Returns true in case of an error, false otherwise. static bool ReadCheckFile(SourceMgr &SM, std::vector &CheckStrings) { - OwningPtr File; - if (error_code ec = - MemoryBuffer::getFileOrSTDIN(CheckFilename, File)) { - errs() << "Could not open check file '" << CheckFilename << "': " - << ec.message() << '\n'; + ErrorOr> FileOrErr = + MemoryBuffer::getFileOrSTDIN(CheckFilename); + if (std::error_code EC = FileOrErr.getError()) { + errs() << "Could not open check file '" << CheckFilename + << "': " << EC.message() << '\n'; return true; } // If we want to canonicalize whitespace, strip excess whitespace from the // buffer containing the CHECK lines. Remove DOS style line endings. - MemoryBuffer *F = - CanonicalizeInputFile(File.take(), NoCanonicalizeWhiteSpace); - - SM.AddNewSourceBuffer(F, SMLoc()); + std::unique_ptr F = CanonicalizeInputFile( + std::move(FileOrErr.get()), NoCanonicalizeWhiteSpace); // Find all instances of CheckPrefix followed by : in the file. StringRef Buffer = F->getBuffer(); - std::vector DagNotMatches; + + SM.AddNewSourceBuffer(std::move(F), SMLoc()); + + std::vector ImplicitNegativeChecks; + for (const auto &PatternString : ImplicitCheckNot) { + // Create a buffer with fake command line content in order to display the + // command line option responsible for the specific implicit CHECK-NOT. + std::string Prefix = std::string("-") + ImplicitCheckNot.ArgStr + "='"; + std::string Suffix = "'"; + std::unique_ptr CmdLine = MemoryBuffer::getMemBufferCopy( + Prefix + PatternString + Suffix, "command line"); + + StringRef PatternInBuffer = + CmdLine->getBuffer().substr(Prefix.size(), PatternString.size()); + SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc()); + + ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot)); + ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer, + "IMPLICIT-CHECK", SM, 0); + } + + + std::vector DagNotMatches = ImplicitNegativeChecks; // LineNumber keeps track of the line on which CheckPrefix instances are // found. @@ -911,6 +939,7 @@ static bool ReadCheckFile(SourceMgr &SM, PatternLoc, CheckTy)); std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); + DagNotMatches = ImplicitNegativeChecks; } // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first @@ -966,7 +995,8 @@ static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr, /// CountNumNewlinesBetween - Count the number of newlines in the specified /// range. -static unsigned CountNumNewlinesBetween(StringRef Range) { +static unsigned CountNumNewlinesBetween(StringRef Range, + const char *&FirstNewLine) { unsigned NumNewLines = 0; while (1) { // Scan for newline. @@ -981,6 +1011,9 @@ static unsigned CountNumNewlinesBetween(StringRef Range) { (Range[0] != Range[1])) Range = Range.substr(1); Range = Range.substr(1); + + if (NumNewLines == 1) + FirstNewLine = Range.begin(); } } @@ -1040,7 +1073,8 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { SMLoc::getFromPointer(Buffer.data())))->getBufferStart() && "CHECK-NEXT can't be the first check in a file"); - unsigned NumNewLines = CountNumNewlinesBetween(Buffer); + const char *FirstNewLine = nullptr; + unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); if (NumNewLines == 0) { SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix + @@ -1059,6 +1093,8 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { SourceMgr::DK_Note, "'next' match was here"); SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, "previous match ended here"); + SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note, + "non-matching line after previous match is here"); return true; } @@ -1179,7 +1215,11 @@ static bool ValidateCheckPrefixes() { I != E; ++I) { StringRef Prefix(*I); - if (!PrefixSet.insert(Prefix)) + // Reject empty prefixes. + if (Prefix == "") + return false; + + if (!PrefixSet.insert(Prefix).second) return false; if (!ValidateCheckPrefix(Prefix)) @@ -1218,33 +1258,34 @@ int main(int argc, char **argv) { return 2; // Open the file to check and add it to SourceMgr. - OwningPtr File; - if (error_code ec = - MemoryBuffer::getFileOrSTDIN(InputFilename, File)) { - errs() << "Could not open input file '" << InputFilename << "': " - << ec.message() << '\n'; + ErrorOr> FileOrErr = + MemoryBuffer::getFileOrSTDIN(InputFilename); + if (std::error_code EC = FileOrErr.getError()) { + errs() << "Could not open input file '" << InputFilename + << "': " << EC.message() << '\n'; return 2; } + std::unique_ptr &File = FileOrErr.get(); - if (File->getBufferSize() == 0) { + if (File->getBufferSize() == 0 && !AllowEmptyInput) { errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; return 2; } // Remove duplicate spaces in the input file if requested. // Remove DOS style line endings. - MemoryBuffer *F = - CanonicalizeInputFile(File.take(), NoCanonicalizeWhiteSpace); - - SM.AddNewSourceBuffer(F, SMLoc()); - - /// VariableTable - This holds all the current filecheck variables. - StringMap VariableTable; + std::unique_ptr F = + CanonicalizeInputFile(std::move(File), NoCanonicalizeWhiteSpace); // Check that we have all of the expected strings, in order, in the input // file. StringRef Buffer = F->getBuffer(); + SM.AddNewSourceBuffer(std::move(F), SMLoc()); + + /// VariableTable - This holds all the current filecheck variables. + StringMap VariableTable; + bool hasError = false; unsigned i = 0, j = 0, e = CheckStrings.size();