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 @@ -1495,6 +1495,37 @@ } }; +// Specialization for ManagedStatic>. +template +class list_storage>> { + using StorageClass = ManagedStatic>; + StorageClass *Location = nullptr; // Where to store the object... + +public: + list_storage() = default; + + void clear() { + getStorageClass()->clear(); + } + + bool setLocation(Option &O, StorageClass &L) { + if (Location) + return O.error("cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template void addValue(const T &V) { + getStorageClass()->push_back(V); + } +private: + StorageClass &getStorageClass() { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage!"); + return *Location; + } +}; + // Define how to hold a class type object, such as a string. // Originally this code inherited from std::vector. In transitioning to a new // API for command line options we should change this. The new implementation diff --git a/llvm/lib/Support/Debug.cpp b/llvm/lib/Support/Debug.cpp --- a/llvm/lib/Support/Debug.cpp +++ b/llvm/lib/Support/Debug.cpp @@ -95,28 +95,14 @@ cl::Hidden, cl::init(0)); -namespace { - -struct DebugOnlyOpt { - void operator=(const std::string &Val) const { - if (Val.empty()) - return; - DebugFlag = true; - SmallVector dbgTypes; - StringRef(Val).split(dbgTypes, ',', -1, false); - for (auto dbgType : dbgTypes) - CurrentDebugType->push_back(dbgType); - } -}; - -} - -static DebugOnlyOpt DebugOnlyOptLoc; +static cl::list>> + DebugOnly("debug-only", + cl::desc("Enable a specific type of debug output (comma " + "separated list of types)"), + cl::Hidden, cl::ZeroOrMore, cl::value_desc("debug string"), + cl::location(CurrentDebugType), cl::CommaSeparated, + cl::callback([](const std::string &) { DebugFlag = true; })); -static cl::opt > -DebugOnly("debug-only", cl::desc("Enable a specific type of debug output (comma separated list of types)"), - cl::Hidden, cl::ZeroOrMore, cl::value_desc("debug string"), - cl::location(DebugOnlyOptLoc), cl::ValueRequired); // Signal handlers - dump debug output on termination. static void debug_user_sig_handler(void *Cookie) { // This is a bit sneaky. Since this is under #ifndef NDEBUG, we 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 @@ -1784,4 +1784,30 @@ cl::ResetAllOptionOccurrences(); } + +TEST(CommandLineTest, ManagedStaticLocation) { + cl::ResetCommandLineParser(); + + ManagedStatic> ManagedStringVec; + + StackOption OptA("a", cl::desc("option a")); + StackOption>>> + ManagedList( + "managedlist", + cl::desc("option managedlist -- This option turns on options a when " + "'foo' is included in list"), + cl::location(ManagedStringVec), cl::CommaSeparated, + cl::callback([&](const std::string &Str) { + if (Str == "foo") + OptA = true; + })); + + const char *args[] = {"prog", "--managedlist=foo"}; + EXPECT_TRUE(cl::ParseCommandLineOptions(2, args)); + EXPECT_TRUE(OptA); + EXPECT_TRUE(ManagedStringVec->size() == 1); + + cl::ResetAllOptionOccurrences(); +} } // anonymous namespace