diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h --- a/llvm/include/llvm/Support/CommandLine.h +++ b/llvm/include/llvm/Support/CommandLine.h @@ -232,7 +232,7 @@ SmallVector PositionalOpts; SmallVector SinkOpts; - StringMap OptionsMap; + DenseMap OptionsMap; Option *ConsumeAfterOpt = nullptr; // The ConsumeAfter option if it exists. }; @@ -1242,15 +1242,18 @@ //===----------------------------------------------------------------------===// // This class is used because we must use partial specialization to handle -// literal string arguments specially (const char* does not correctly respond to -// the apply method). Because the syntax to use this is a pain, we have the -// 'apply' method below to handle the nastiness... +// literal string arguments specially (const char[...] does not correctly +// respond to the apply method). Because the syntax to use this is a pain, we +// have the 'apply' method below to handle the nastiness... +// +// Note that char * and StringRef are not part of the specialization, which +// helps preventing reference to stack variables (but doesn't totally prevents +// it, unfortunately). // template struct applicator { template static void opt(const Mod &M, Opt &O) { M.apply(O); } }; -// Handle const char* as a special case... template struct applicator { template static void opt(StringRef Str, Opt &O) { O.setArgStr(Str); @@ -1261,7 +1264,7 @@ O.setArgStr(Str); } }; -template <> struct applicator { +template <> struct applicator { template static void opt(StringRef Str, Opt &O) { O.setArgStr(Str); } @@ -2017,7 +2020,7 @@ /// Hopefully this API can be deprecated soon. Any situation where options need /// to be modified by tools or libraries should be handled by sane APIs rather /// than just handing around a global list. -StringMap & +DenseMap & getRegisteredOptions(SubCommand &Sub = SubCommand::getTopLevel()); /// Use this to get all registered SubCommands from the provided parser. diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -210,28 +210,28 @@ /// Option names for limiting the codegen pipeline. /// Those are used in error reporting and we didn't want /// to duplicate their names all over the place. -static const char StartAfterOptName[] = "start-after"; -static const char StartBeforeOptName[] = "start-before"; -static const char StopAfterOptName[] = "stop-after"; -static const char StopBeforeOptName[] = "stop-before"; +static const StringLiteral StartAfterOptName = "start-after"; +static const StringLiteral StartBeforeOptName = "start-before"; +static const StringLiteral StopAfterOptName = "stop-after"; +static const StringLiteral StopBeforeOptName = "stop-before"; static cl::opt - StartAfterOpt(StringRef(StartAfterOptName), + StartAfterOpt(StartAfterOptName, cl::desc("Resume compilation after a specific pass"), cl::value_desc("pass-name"), cl::init(""), cl::Hidden); static cl::opt - StartBeforeOpt(StringRef(StartBeforeOptName), + StartBeforeOpt(StartBeforeOptName, cl::desc("Resume compilation before a specific pass"), cl::value_desc("pass-name"), cl::init(""), cl::Hidden); static cl::opt - StopAfterOpt(StringRef(StopAfterOptName), + StopAfterOpt(StopAfterOptName, cl::desc("Stop compilation after a specific pass"), cl::value_desc("pass-name"), cl::init(""), cl::Hidden); static cl::opt - StopBeforeOpt(StringRef(StopBeforeOptName), + StopBeforeOpt(StopBeforeOptName, cl::desc("Stop compilation before a specific pass"), cl::value_desc("pass-name"), cl::init(""), cl::Hidden); @@ -406,8 +406,7 @@ const PassRegistry &PR = *PassRegistry::getPassRegistry(); const PassInfo *PI = PR.getPassInfo(PassName); if (!PI) - report_fatal_error(Twine('\"') + Twine(PassName) + - Twine("\" pass is not registered.")); + report_fatal_error("\"" + PassName + "\" pass is not registered."); return PI; } @@ -450,11 +449,11 @@ StopBefore = getPassIDFromName(StopBeforeName); StopAfter = getPassIDFromName(StopAfterName); if (StartBefore && StartAfter) - report_fatal_error(Twine(StartBeforeOptName) + Twine(" and ") + - Twine(StartAfterOptName) + Twine(" specified!")); + report_fatal_error(StartBeforeOptName + " and " + StartAfterOptName + + " specified!"); if (StopBefore && StopAfter) - report_fatal_error(Twine(StopBeforeOptName) + Twine(" and ") + - Twine(StopAfterOptName) + Twine(" specified!")); + report_fatal_error(StopBeforeOptName + " and " + StopAfterOptName + + " specified!"); Started = (StartAfter == nullptr) && (StartBefore == nullptr); } @@ -526,11 +525,11 @@ std::tie(StopAfter, std::ignore) = LLVMTM.getPassNameFromLegacyName(StopAfter); if (!StartBefore.empty() && !StartAfter.empty()) - report_fatal_error(Twine(StartBeforeOptName) + Twine(" and ") + - Twine(StartAfterOptName) + Twine(" specified!")); + report_fatal_error(StartBeforeOptName + " and " + StartAfterOptName + + " specified!"); if (!StopBefore.empty() && !StopAfter.empty()) - report_fatal_error(Twine(StopBeforeOptName) + Twine(" and ") + - Twine(StopAfterOptName) + Twine(" specified!")); + report_fatal_error(StopBeforeOptName + " and " + StopAfterOptName + + " specified!"); PIC.registerShouldRunOptionalPassCallback( [=, EnableCurrent = StartBefore.empty() && StartAfter.empty(), @@ -673,8 +672,8 @@ std::string Res; static cl::opt *PassNames[] = {&StartAfterOpt, &StartBeforeOpt, &StopAfterOpt, &StopBeforeOpt}; - static const char *OptNames[] = {StartAfterOptName, StartBeforeOptName, - StopAfterOptName, StopBeforeOptName}; + static StringLiteral OptNames[] = {StartAfterOptName, StartBeforeOptName, + StopAfterOptName, StopBeforeOptName}; bool IsFirst = true; for (int Idx = 0; Idx < 4; ++Idx) if (!PassNames[Idx]->empty()) { diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp --- a/llvm/lib/Support/CommandLine.cpp +++ b/llvm/lib/Support/CommandLine.cpp @@ -275,7 +275,7 @@ auto End = Sub.OptionsMap.end(); for (auto Name : OptionNames) { auto I = Sub.OptionsMap.find(Name); - if (I != End && I->getValue() == O) + if (I != End && I->second == O) Sub.OptionsMap.erase(I); } @@ -381,7 +381,7 @@ O->hasArgStr()) addOption(O, sub); else - addLiteralOption(*O, sub, E.first()); + addLiteralOption(*O, sub, E.first); } } } @@ -570,9 +570,10 @@ /// the specified option on the command line. If there is a value specified /// (after an equal sign) return that as well. This assumes that leading dashes /// have already been stripped. -static Option *LookupNearestOption(StringRef Arg, - const StringMap &OptionsMap, - std::string &NearestString) { +static Option * +LookupNearestOption(StringRef Arg, + const DenseMap &OptionsMap, + std::string &NearestString) { // Reject all dashes. if (Arg.empty()) return nullptr; @@ -585,8 +586,8 @@ // Find the closest match. Option *Best = nullptr; unsigned BestDistance = 0; - for (StringMap::const_iterator it = OptionsMap.begin(), - ie = OptionsMap.end(); + for (DenseMap::const_iterator it = OptionsMap.begin(), + ie = OptionsMap.end(); it != ie; ++it) { Option *O = it->second; // Do not suggest really hidden options (not shown in any help). @@ -720,9 +721,9 @@ // static Option *getOptionPred(StringRef Name, size_t &Length, bool (*Pred)(const Option *), - const StringMap &OptionsMap) { - StringMap::const_iterator OMI = OptionsMap.find(Name); - if (OMI != OptionsMap.end() && !Pred(OMI->getValue())) + const DenseMap &OptionsMap) { + DenseMap::const_iterator OMI = OptionsMap.find(Name); + if (OMI != OptionsMap.end() && !Pred(OMI->second)) OMI = OptionsMap.end(); // Loop while we haven't found an option and Name still has at least two @@ -731,7 +732,7 @@ while (OMI == OptionsMap.end() && Name.size() > 1) { Name = Name.substr(0, Name.size() - 1); // Chop off the last character. OMI = OptionsMap.find(Name); - if (OMI != OptionsMap.end() && !Pred(OMI->getValue())) + if (OMI != OptionsMap.end() && !Pred(OMI->second)) OMI = OptionsMap.end(); } @@ -749,7 +750,7 @@ static Option * HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value, bool &ErrorParsing, - const StringMap &OptionsMap) { + const DenseMap &OptionsMap) { if (Arg.size() == 1) return nullptr; @@ -2271,12 +2272,13 @@ } // Copy Options into a vector so we can sort them as we like. -static void sortOpts(StringMap &OptMap, +static void sortOpts(DenseMap &OptMap, SmallVectorImpl> &Opts, bool ShowHidden) { SmallPtrSet OptionSet; // Duplicate option detection. - for (StringMap::iterator I = OptMap.begin(), E = OptMap.end(); + for (DenseMap::iterator I = OptMap.begin(), + E = OptMap.end(); I != E; ++I) { // Ignore really-hidden options. if (I->second->getOptionHiddenFlag() == ReallyHidden) @@ -2291,7 +2293,7 @@ continue; Opts.push_back( - std::pair(I->getKey().data(), I->second)); + std::pair(I->first.data(), I->second)); } // Sort the options list alphabetically. @@ -2754,7 +2756,7 @@ CommonOptions->ExtraVersionPrinters.push_back(func); } -StringMap &cl::getRegisteredOptions(SubCommand &Sub) { +DenseMap &cl::getRegisteredOptions(SubCommand &Sub) { initCommonOptions(); auto &Subs = GlobalParser->RegisteredSubCommands; (void)Subs; diff --git a/llvm/unittests/Support/CommandLineInit/CommandLineInitTest.cpp b/llvm/unittests/Support/CommandLineInit/CommandLineInitTest.cpp --- a/llvm/unittests/Support/CommandLineInit/CommandLineInitTest.cpp +++ b/llvm/unittests/Support/CommandLineInit/CommandLineInitTest.cpp @@ -50,7 +50,7 @@ } TEST(CommandLineInitTest, GetPresetOptions) { - StringMap &Map = + DenseMap &Map = cl::getRegisteredOptions(cl::SubCommand::getTopLevel()); for (auto *Str : diff --git a/llvm/unittests/Support/CommandLineTest.cpp b/llvm/unittests/Support/CommandLineTest.cpp --- a/llvm/unittests/Support/CommandLineTest.cpp +++ b/llvm/unittests/Support/CommandLineTest.cpp @@ -98,7 +98,7 @@ static const char ArgString[] = "new-test-option"; static const char ValueString[] = "Integer"; - StringMap &Map = + DenseMap &Map = cl::getRegisteredOptions(cl::SubCommand::getTopLevel()); ASSERT_EQ(Map.count("test-option"), 1u) << "Could not find option in map."; @@ -419,7 +419,7 @@ ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag()) << "Hid extra option that should be visable."; - StringMap &Map = + DenseMap &Map = cl::getRegisteredOptions(cl::SubCommand::getTopLevel()); ASSERT_TRUE(Map.count("help") == (size_t)0 || cl::NotHidden == Map["help"]->getOptionHiddenFlag()) @@ -445,7 +445,7 @@ ASSERT_EQ(cl::NotHidden, TestOption3.getOptionHiddenFlag()) << "Hid extra option that should be visable."; - StringMap &Map = + DenseMap &Map = cl::getRegisteredOptions(cl::SubCommand::getTopLevel()); ASSERT_TRUE(Map.count("help") == (size_t)0 || cl::NotHidden == Map["help"]->getOptionHiddenFlag()) @@ -1319,7 +1319,7 @@ } enum class OptionValue { Val }; - const StringRef Opt = "some-option"; + const StringLiteral Opt = "some-option"; const StringRef HelpText = "some help"; private: @@ -1421,7 +1421,7 @@ enum class OptionValue { Val }; template - size_t runTest(StringRef ArgName, Ts... OptionAttributes) { + size_t runTest(StringLiteral ArgName, Ts... OptionAttributes) { StackOption TestOption(ArgName, cl::desc("some help"), OptionAttributes...); return getOptionWidth(TestOption); @@ -1435,7 +1435,7 @@ }; TEST_F(GetOptionWidthTest, GetOptionWidthArgNameLonger) { - StringRef ArgName("a-long-argument-name"); + StringLiteral ArgName("a-long-argument-name"); size_t ExpectedStrSize = (" --" + ArgName + "= - ").str().size(); EXPECT_EQ( runTest(ArgName, cl::values(clEnumValN(OptionValue::Val, "v", "help"))), @@ -1443,7 +1443,7 @@ } TEST_F(GetOptionWidthTest, GetOptionWidthFirstOptionNameLonger) { - StringRef OptName("a-long-option-name"); + StringLiteral OptName("a-long-option-name"); size_t ExpectedStrSize = (" =" + OptName + " - ").str().size(); EXPECT_EQ( runTest("a", cl::values(clEnumValN(OptionValue::Val, OptName, "help"), @@ -1452,7 +1452,7 @@ } TEST_F(GetOptionWidthTest, GetOptionWidthSecondOptionNameLonger) { - StringRef OptName("a-long-option-name"); + StringLiteral OptName("a-long-option-name"); size_t ExpectedStrSize = (" =" + OptName + " - ").str().size(); EXPECT_EQ( runTest("a", cl::values(clEnumValN(OptionValue::Val, "b", "help"), @@ -1472,7 +1472,7 @@ TEST_F(GetOptionWidthTest, GetOptionWidthValueOptionalEmptyOptionWithNoDescription) { - StringRef ArgName("a"); + StringLiteral ArgName("a"); // The length of a= (including indentation) is actually the same as the // = string, so it is impossible to distinguish via testing the case // where the empty string is ignored from where it is not ignored.