Index: llvm/include/llvm/Support/FileCheck.h =================================================================== --- llvm/include/llvm/Support/FileCheck.h +++ llvm/include/llvm/Support/FileCheck.h @@ -24,10 +24,10 @@ /// Contains info about various FileCheck options. struct FileCheckRequest { - std::vector CheckPrefixes; + std::vector CheckPrefixes; bool NoCanonicalizeWhiteSpace = false; - std::vector ImplicitCheckNot; - std::vector GlobalDefines; + std::vector ImplicitCheckNot; + std::vector GlobalDefines; bool AllowEmptyInput = false; bool MatchFullLines = false; bool IgnoreCase = false; Index: llvm/lib/Support/FileCheck.cpp =================================================================== --- llvm/lib/Support/FileCheck.cpp +++ llvm/lib/Support/FileCheck.cpp @@ -1281,13 +1281,13 @@ PatternContext->createLineVariable(); std::vector ImplicitNegativeChecks; - for (const auto &PatternString : Req.ImplicitCheckNot) { + for (StringRef PatternString : Req.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 = "-implicit-check-not='"; std::string Suffix = "'"; std::unique_ptr CmdLine = MemoryBuffer::getMemBufferCopy( - Prefix + PatternString + Suffix, "command line"); + (Prefix + PatternString + Suffix).str(), "command line"); StringRef PatternInBuffer = CmdLine->getBuffer().substr(Prefix.size(), PatternString.size()); @@ -1403,22 +1403,18 @@ if (!DagNotMatches.empty()) { CheckStrings->emplace_back( Pattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1), - *Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data())); + Req.CheckPrefixes.front(), SMLoc::getFromPointer(Buffer.data())); std::swap(DagNotMatches, CheckStrings->back().DagNotStrings); } if (CheckStrings->empty()) { errs() << "error: no check strings found with prefix" << (Req.CheckPrefixes.size() > 1 ? "es " : " "); - auto I = Req.CheckPrefixes.begin(); - auto E = Req.CheckPrefixes.end(); - if (I != E) { - errs() << "\'" << *I << ":'"; - ++I; + for (size_t I = 0, E = Req.CheckPrefixes.size(); I != E; ++I) { + if (I != 0) + errs() << ", "; + errs() << "\'" << Req.CheckPrefixes[I] << ":'"; } - for (; I != E; ++I) - errs() << ", \'" << *I << ":'"; - errs() << '\n'; return true; } @@ -1872,7 +1868,7 @@ for (StringRef Prefix : Req.CheckPrefixes) { // Reject empty prefixes. - if (Prefix == "") + if (Prefix.empty()) return false; if (!PrefixSet.insert(Prefix).second) @@ -1894,18 +1890,17 @@ // We already validated the contents of CheckPrefixes so just concatenate // them as alternatives. SmallString<32> PrefixRegexStr; - for (StringRef Prefix : Req.CheckPrefixes) { - if (Prefix != Req.CheckPrefixes.front()) + for (size_t I = 0, E = Req.CheckPrefixes.size(); I != E; ++I) { + if (I != 0) PrefixRegexStr.push_back('|'); - - PrefixRegexStr.append(Prefix); + PrefixRegexStr.append(Req.CheckPrefixes[I]); } return Regex(PrefixRegexStr); } Error FileCheckPatternContext::defineCmdlineVariables( - std::vector &CmdlineDefines, SourceMgr &SM) { + ArrayRef CmdlineDefines, SourceMgr &SM) { assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() && "Overriding defined variable with command-line variable definitions"); Index: llvm/lib/Support/FileCheckImpl.h =================================================================== --- llvm/lib/Support/FileCheckImpl.h +++ llvm/lib/Support/FileCheckImpl.h @@ -407,7 +407,7 @@ /// command line, passed as a vector of [#]VAR=VAL strings in /// \p CmdlineDefines. \returns an error list containing diagnostics against /// \p SM for all definition parsing failures, if any, or Success otherwise. - Error defineCmdlineVariables(std::vector &CmdlineDefines, + Error defineCmdlineVariables(ArrayRef CmdlineDefines, SourceMgr &SM); /// Create @LINE pseudo variable. Value is set when pattern are being Index: llvm/unittests/Support/FileCheckTest.cpp =================================================================== --- llvm/unittests/Support/FileCheckTest.cpp +++ llvm/unittests/Support/FileCheckTest.cpp @@ -528,9 +528,7 @@ public: PatternTester() { - std::vector GlobalDefines; - GlobalDefines.emplace_back(std::string("#FOO=42")); - GlobalDefines.emplace_back(std::string("BAR=BAZ")); + std::vector GlobalDefines = {"#FOO=42", "BAR=BAZ"}; // An ASSERT_FALSE would make more sense but cannot be used in a // constructor. EXPECT_THAT_ERROR(Context.defineCmdlineVariables(GlobalDefines, SM), @@ -849,9 +847,7 @@ TEST_F(FileCheckTest, Substitution) { SourceMgr SM; FileCheckPatternContext Context; - std::vector GlobalDefines; - GlobalDefines.emplace_back(std::string("FOO=BAR")); - EXPECT_THAT_ERROR(Context.defineCmdlineVariables(GlobalDefines, SM), + EXPECT_THAT_ERROR(Context.defineCmdlineVariables({"FOO=BAR"}, SM), Succeeded()); // Substitution of an undefined string variable fails and error holds that @@ -890,72 +886,53 @@ TEST_F(FileCheckTest, FileCheckContext) { FileCheckPatternContext Cxt; - std::vector GlobalDefines; SourceMgr SM; // No definition. - EXPECT_THAT_ERROR(Cxt.defineCmdlineVariables(GlobalDefines, SM), Succeeded()); + EXPECT_THAT_ERROR(Cxt.defineCmdlineVariables({}, SM), Succeeded()); // Missing equal sign. - GlobalDefines.emplace_back(std::string("LocalVar")); expectDiagnosticError("missing equal sign in global definition", - Cxt.defineCmdlineVariables(GlobalDefines, SM)); - GlobalDefines.clear(); - GlobalDefines.emplace_back(std::string("#LocalNumVar")); + Cxt.defineCmdlineVariables({"LocalVar"}, SM)); expectDiagnosticError("missing equal sign in global definition", - Cxt.defineCmdlineVariables(GlobalDefines, SM)); + Cxt.defineCmdlineVariables({"#LocalNumVar"}, SM)); // Empty variable name. - GlobalDefines.clear(); - GlobalDefines.emplace_back(std::string("=18")); expectDiagnosticError("empty variable name", - Cxt.defineCmdlineVariables(GlobalDefines, SM)); - GlobalDefines.clear(); - GlobalDefines.emplace_back(std::string("#=18")); + Cxt.defineCmdlineVariables({"=18"}, SM)); expectDiagnosticError("empty variable name", - Cxt.defineCmdlineVariables(GlobalDefines, SM)); + Cxt.defineCmdlineVariables({"#=18"}, SM)); // Invalid variable name. - GlobalDefines.clear(); - GlobalDefines.emplace_back(std::string("18LocalVar=18")); expectDiagnosticError("invalid variable name", - Cxt.defineCmdlineVariables(GlobalDefines, SM)); - GlobalDefines.clear(); - GlobalDefines.emplace_back(std::string("#18LocalNumVar=18")); + Cxt.defineCmdlineVariables({"18LocalVar=18"}, SM)); expectDiagnosticError("invalid variable name", - Cxt.defineCmdlineVariables(GlobalDefines, SM)); + Cxt.defineCmdlineVariables({"#18LocalNumVar=18"}, SM)); // Name conflict between pattern and numeric variable. - GlobalDefines.clear(); - GlobalDefines.emplace_back(std::string("LocalVar=18")); - GlobalDefines.emplace_back(std::string("#LocalVar=36")); - expectDiagnosticError("string variable with name 'LocalVar' already exists", - Cxt.defineCmdlineVariables(GlobalDefines, SM)); + expectDiagnosticError( + "string variable with name 'LocalVar' already exists", + Cxt.defineCmdlineVariables({"LocalVar=18", "#LocalVar=36"}, SM)); Cxt = FileCheckPatternContext(); - GlobalDefines.clear(); - GlobalDefines.emplace_back(std::string("#LocalNumVar=18")); - GlobalDefines.emplace_back(std::string("LocalNumVar=36")); expectDiagnosticError( "numeric variable with name 'LocalNumVar' already exists", - Cxt.defineCmdlineVariables(GlobalDefines, SM)); + Cxt.defineCmdlineVariables({"#LocalNumVar=18", "LocalNumVar=36"}, SM)); Cxt = FileCheckPatternContext(); // Invalid numeric value for numeric variable. - GlobalDefines.clear(); - GlobalDefines.emplace_back(std::string("#LocalNumVar=x")); - expectUndefErrors({"x"}, Cxt.defineCmdlineVariables(GlobalDefines, SM)); + expectUndefErrors({"x"}, Cxt.defineCmdlineVariables({"#LocalNumVar=x"}, SM)); // Define local variables from command-line. - GlobalDefines.clear(); + std::vector GlobalDefines; // Clear local variables to remove dummy numeric variable x that // parseNumericSubstitutionBlock would have created and stored in // GlobalNumericVariableTable. Cxt.clearLocalVars(); - GlobalDefines.emplace_back(std::string("LocalVar=FOO")); - GlobalDefines.emplace_back(std::string("EmptyVar=")); - GlobalDefines.emplace_back(std::string("#LocalNumVar1=18")); - GlobalDefines.emplace_back(std::string("#%x,LocalNumVar2=LocalNumVar1+2")); - GlobalDefines.emplace_back(std::string("#LocalNumVar3=0xc")); + GlobalDefines.emplace_back("LocalVar=FOO"); + GlobalDefines.emplace_back("EmptyVar="); + GlobalDefines.emplace_back("#LocalNumVar1=18"); + GlobalDefines.emplace_back("#%x,LocalNumVar2=LocalNumVar1+2"); + GlobalDefines.emplace_back("#LocalNumVar3=0xc"); ASSERT_THAT_ERROR(Cxt.defineCmdlineVariables(GlobalDefines, SM), Succeeded()); // Create @LINE pseudo numeric variable and check it is present by matching @@ -1045,8 +1022,8 @@ Cxt.clearLocalVars(); // Redefine global variables and check variables are defined again. - GlobalDefines.emplace_back(std::string("$GlobalVar=BAR")); - GlobalDefines.emplace_back(std::string("#$GlobalNumVar=36")); + GlobalDefines.emplace_back("$GlobalVar=BAR"); + GlobalDefines.emplace_back("#$GlobalNumVar=36"); ASSERT_THAT_ERROR(Cxt.defineCmdlineVariables(GlobalDefines, SM), Succeeded()); StringRef GlobalVarStr = "$GlobalVar"; StringRef GlobalNumVarRef = bufferize(SM, "$GlobalNumVar"); Index: llvm/utils/FileCheck/FileCheck.cpp =================================================================== --- llvm/utils/FileCheck/FileCheck.cpp +++ llvm/utils/FileCheck/FileCheck.cpp @@ -534,14 +534,17 @@ } FileCheckRequest Req; - for (auto Prefix : CheckPrefixes) - Req.CheckPrefixes.push_back(Prefix); + // We do not want to rely on the storage of cl::list, because it + // is probably a bit subtle. So we copy strings instead. + BumpPtrAllocator StrAlloc; + for (StringRef Prefix : CheckPrefixes) + Req.CheckPrefixes.push_back(Prefix.copy(StrAlloc)); - for (auto CheckNot : ImplicitCheckNot) - Req.ImplicitCheckNot.push_back(CheckNot); + for (StringRef CheckNot : ImplicitCheckNot) + Req.ImplicitCheckNot.push_back(CheckNot.copy(StrAlloc)); bool GlobalDefineError = false; - for (auto G : GlobalDefines) { + for (StringRef G : GlobalDefines) { size_t EqIdx = G.find('='); if (EqIdx == std::string::npos) { errs() << "Missing equal sign in command-line definition '-D" << G @@ -555,7 +558,7 @@ GlobalDefineError = true; continue; } - Req.GlobalDefines.push_back(G); + Req.GlobalDefines.push_back(G.copy(StrAlloc)); } if (GlobalDefineError) return 2;