diff --git a/llvm/include/llvm/Support/FileCheck.h b/llvm/include/llvm/Support/FileCheck.h --- a/llvm/include/llvm/Support/FileCheck.h +++ b/llvm/include/llvm/Support/FileCheck.h @@ -728,10 +728,13 @@ /// use information from the request. class FileCheck { FileCheckRequest Req; - FileCheckPatternContext PatternContext; + std::unique_ptr PatternContext; + // C++17 TODO: make this a plain std::vector. + std::unique_ptr> CheckStrings; public: - FileCheck(FileCheckRequest Req) : Req(Req) {} + explicit FileCheck(FileCheckRequest Req); + ~FileCheck(); // Combines the check prefixes into a single regex so that we can efficiently // scan for any of the set. @@ -741,13 +744,11 @@ Regex buildCheckPrefixRegex(); /// Reads the check file from \p Buffer and records the expected strings it - /// contains in the \p CheckStrings vector. Errors are reported against - /// \p SM. + /// contains. Errors are reported against \p SM. /// /// Only expected strings whose prefix is one of those listed in \p PrefixRE /// are recorded. \returns true in case of an error, false otherwise. - bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, - std::vector &CheckStrings); + bool readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE); bool ValidateCheckPrefixes(); @@ -757,12 +758,11 @@ SmallVectorImpl &OutputBuffer); /// Checks the input to FileCheck provided in the \p Buffer against the - /// \p CheckStrings read from the check file and record diagnostics emitted + /// expected strings read from the check file and record diagnostics emitted /// in \p Diags. Errors are recorded against \p SM. /// /// \returns false if the input fails to satisfy the checks. - bool CheckInput(SourceMgr &SM, StringRef Buffer, - ArrayRef CheckStrings, + bool checkInput(SourceMgr &SM, StringRef Buffer, std::vector *Diags = nullptr); }; } // namespace llvm diff --git a/llvm/lib/Support/FileCheck.cpp b/llvm/lib/Support/FileCheck.cpp --- a/llvm/lib/Support/FileCheck.cpp +++ b/llvm/lib/Support/FileCheck.cpp @@ -1116,16 +1116,22 @@ GlobalNumericVariableTable[LineName] = LineVariable; } -bool FileCheck::ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, - std::vector &CheckStrings) { +FileCheck::FileCheck(FileCheckRequest Req) + : Req(Req), PatternContext(std::make_unique()), + CheckStrings(std::make_unique>()) {} + +FileCheck::~FileCheck() = default; + +bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer, + Regex &PrefixRE) { Error DefineError = - PatternContext.defineCmdlineVariables(Req.GlobalDefines, SM); + PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM); if (DefineError) { logAllUnhandledErrors(std::move(DefineError), errs()); return true; } - PatternContext.createLineVariable(); + PatternContext->createLineVariable(); std::vector ImplicitNegativeChecks; for (const auto &PatternString : Req.ImplicitCheckNot) { @@ -1141,7 +1147,7 @@ SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc()); ImplicitNegativeChecks.push_back( - FileCheckPattern(Check::CheckNot, &PatternContext)); + FileCheckPattern(Check::CheckNot, PatternContext.get())); ImplicitNegativeChecks.back().parsePattern(PatternInBuffer, "IMPLICIT-CHECK", SM, Req); } @@ -1204,7 +1210,7 @@ SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); // Parse the pattern. - FileCheckPattern P(CheckTy, &PatternContext, LineNumber); + FileCheckPattern P(CheckTy, PatternContext.get(), LineNumber); if (P.parsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, Req)) return true; @@ -1222,7 +1228,7 @@ // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them. if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame || CheckTy == Check::CheckEmpty) && - CheckStrings.empty()) { + CheckStrings->empty()) { StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME"; @@ -1240,21 +1246,21 @@ } // Okay, add the string we captured to the output vector and move on. - CheckStrings.emplace_back(P, UsedPrefix, PatternLoc); - std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); + CheckStrings->emplace_back(P, UsedPrefix, PatternLoc); + std::swap(DagNotMatches, CheckStrings->back().DagNotStrings); DagNotMatches = ImplicitNegativeChecks; } // 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.emplace_back( - FileCheckPattern(Check::CheckEOF, &PatternContext, LineNumber + 1), + CheckStrings->emplace_back( + FileCheckPattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1), *Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data())); - std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); + std::swap(DagNotMatches, CheckStrings->back().DagNotStrings); } - if (CheckStrings.empty()) { + if (CheckStrings->empty()) { errs() << "error: no check strings found with prefix" << (Req.CheckPrefixes.size() > 1 ? "es " : " "); auto I = Req.CheckPrefixes.begin(); @@ -1916,18 +1922,17 @@ GlobalNumericVariableTable.erase(Var); } -bool FileCheck::CheckInput(SourceMgr &SM, StringRef Buffer, - ArrayRef CheckStrings, +bool FileCheck::checkInput(SourceMgr &SM, StringRef Buffer, std::vector *Diags) { bool ChecksFailed = false; - unsigned i = 0, j = 0, e = CheckStrings.size(); + unsigned i = 0, j = 0, e = CheckStrings->size(); while (true) { StringRef CheckRegion; if (j == e) { CheckRegion = Buffer; } else { - const FileCheckString &CheckLabelStr = CheckStrings[j]; + const FileCheckString &CheckLabelStr = (*CheckStrings)[j]; if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) { ++j; continue; @@ -1950,10 +1955,10 @@ // CHECK-LABEL and it would clear variables defined on the command-line // before they get used. if (i != 0 && Req.EnableVarScope) - PatternContext.clearLocalVars(); + PatternContext->clearLocalVars(); for (; i != j; ++i) { - const FileCheckString &CheckStr = CheckStrings[i]; + const FileCheckString &CheckStr = (*CheckStrings)[i]; // Check each string within the scanned region, including a second check // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG) diff --git a/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h b/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h --- a/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h +++ b/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h @@ -195,12 +195,11 @@ SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(CheckFileText, "CheckFile"), SMLoc()); Regex PrefixRE = FC.buildCheckPrefixRegex(); - std::vector CheckStrings; - if (FC.ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings)) + if (FC.readCheckFile(SM, CheckFileText, PrefixRE)) return false; auto OutBuffer = OutputBuf->getBuffer(); SM.AddNewSourceBuffer(std::move(OutputBuf), SMLoc()); - return FC.CheckInput(SM, OutBuffer, CheckStrings); + return FC.checkInput(SM, OutBuffer); } #endif diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp --- a/llvm/utils/FileCheck/FileCheck.cpp +++ b/llvm/utils/FileCheck/FileCheck.cpp @@ -597,8 +597,7 @@ CheckFileText, CheckFile.getBufferIdentifier()), SMLoc()); - std::vector CheckStrings; - if (FC.ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings)) + if (FC.readCheckFile(SM, CheckFileText, PrefixRE)) return 2; // Open the file to check and add it to SourceMgr. @@ -628,7 +627,7 @@ DumpInput = DumpInputOnFailure ? DumpInputFail : DumpInputNever; std::vector Diags; - int ExitCode = FC.CheckInput(SM, InputFileText, CheckStrings, + int ExitCode = FC.checkInput(SM, InputFileText, DumpInput == DumpInputNever ? nullptr : &Diags) ? EXIT_SUCCESS : 1;