template <class Opt> void apply(Opt &O) const { O.setInitialValue(Init); }
};
+template <class Ty> struct list_initializer {
+ ArrayRef<Ty> Inits;
+ list_initializer(ArrayRef<Ty> Vals) : Inits(Vals) {}
+
+ template <class Opt> void apply(Opt &O) const { O.setInitialValues(Inits); }
+};
+
template <class Ty> initializer<Ty> init(const Ty &Val) {
return initializer<Ty>(Val);
}
+template <class Ty>
+list_initializer<Ty> list_init(ArrayRef<Ty> Vals) {
+ return list_initializer<Ty>(Vals);
+}
+
// Allow the user to specify which external variable they want to store the
// results of the command line argument processing into, if they don't want to
// store it in the option itself.
//
template <class DataType, class StorageClass> class list_storage {
StorageClass *Location = nullptr; // Where to store the object...
+ std::vector<OptionValue<DataType>> Default =
+ std::vector<OptionValue<DataType>>();
+ bool DefaultAssigned = false;
public:
list_storage() = default;
return false;
}
- template <class T> void addValue(const T &V) {
+ template <class T> void addValue(const T &V, bool initial = false) {
assert(Location != nullptr &&
"cl::location(...) not specified for a command "
"line option with external storage!");
Location->push_back(V);
+ if (initial)
+ Default.push_back(V);
+ }
+
+ const std::vector<OptionValue<DataType>> &getDefault() const {
+ return Default;
}
+
+ void assignDefault() { DefaultAssigned = true; }
+ void overwriteDefault() { DefaultAssigned = false; }
+ bool isDefaultAssigned() { return DefaultAssigned; }
};
// Define how to hold a class type object, such as a string.
//
template <class DataType> class list_storage<DataType, bool> {
std::vector<DataType> Storage;
+ std::vector<OptionValue<DataType>> Default;
+ bool DefaultAssigned = false;
public:
using iterator = typename std::vector<DataType>::iterator;
std::vector<DataType> *operator&() { return &Storage; }
const std::vector<DataType> *operator&() const { return &Storage; }
- template <class T> void addValue(const T &V) { Storage.push_back(V); }
+ template <class T> void addValue(const T &V, bool initial = false) {
+ Storage.push_back(V);
+ if (initial)
+ Default.push_back(OptionValue<DataType>(V));
+ }
+
+ const std::vector<OptionValue<DataType>> &getDefault() const {
+ return Default;
+ }
+
+ void assignDefault() { DefaultAssigned = true; }
+ void overwriteDefault() { DefaultAssigned = false; }
+ bool isDefaultAssigned() { return DefaultAssigned; }
};
//===----------------------------------------------------------------------===//
StringRef Arg) override {
typename ParserClass::parser_data_type Val =
typename ParserClass::parser_data_type();
+ if (list_storage<DataType, StorageClass>::isDefaultAssigned()) {
+ clear();
+ list_storage<DataType, StorageClass>::overwriteDefault();
+ }
if (Parser.parse(*this, ArgName, Arg, Val))
return true; // Parse Error!
list_storage<DataType, StorageClass>::addValue(Val);
void setDefault() override {
Positions.clear();
list_storage<DataType, StorageClass>::clear();
+ for (auto &Val : list_storage<DataType, StorageClass>::getDefault())
+ list_storage<DataType, StorageClass>::addValue(Val.getValue());
}
void done() {
return Positions[optnum];
}
+ void clear() {
+ Positions.clear();
+ list_storage<DataType, StorageClass>::clear();
+ }
+
+ // setInitialValues - Used by the cl::list_init modifier...
+ void setInitialValues(ArrayRef<DataType> Vs) {
+ assert(!(list_storage<DataType, StorageClass>::isDefaultAssigned()) &&
+ "Cannot have two default values");
+ list_storage<DataType, StorageClass>::assignDefault();
+ for (auto &Val : Vs)
+ list_storage<DataType, StorageClass>::addValue(Val, true);
+ }
+
void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); }
template <class... Mods>
}
}
-TEST(CommandLineTest, SetDefautValue) {
+TEST(CommandLineTest, SetDefaultValue) {
cl::ResetCommandLineParser();
StackOption<std::string> Opt1("opt1", cl::init("true"));
cl::alias Alias("alias", llvm::cl::aliasopt(Opt2));
StackOption<int> Opt3("opt3", cl::init(3));
- const char *args[] = {"prog", "-opt1=false", "-opt2", "-opt3"};
+ llvm::SmallVector<int, 3> IntVals = {1, 2, 3};
+ llvm::SmallVector<std::string, 3> StrVals = {"foo", "bar", "baz"};
+
+ StackOption<int, cl::list<int>> List1(
+ "list1", cl::list_init<int>(llvm::ArrayRef<int>(IntVals)),
+ cl::CommaSeparated);
+ StackOption<std::string, cl::list<std::string>> List2(
+ "list2", cl::list_init<std::string>(llvm::ArrayRef<std::string>(StrVals)),
+ cl::CommaSeparated);
+ cl::alias ListAlias("list-alias", llvm::cl::aliasopt(List2));
+
+ const char *args[] = {"prog", "-opt1=false", "-list1", "4",
+ "-list1", "5,6", "-opt2", "-opt3"};
EXPECT_TRUE(
- cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
+ cl::ParseCommandLineOptions(7, args, StringRef(), &llvm::nulls()));
EXPECT_EQ(Opt1, "false");
EXPECT_TRUE(Opt2);
EXPECT_EQ(Opt3, 3);
+ for (size_t I = 0, E = IntVals.size(); I < E; ++I) {
+ EXPECT_EQ(IntVals[I] + 3, List1[I]);
+ EXPECT_EQ(StrVals[I], List2[I]);
+ }
+
Opt2 = false;
Opt3 = 1;
EXPECT_EQ(Opt1, "true");
EXPECT_TRUE(Opt2);
EXPECT_EQ(Opt3, 3);
+ for (size_t I = 0, E = IntVals.size(); I < E; ++I) {
+ EXPECT_EQ(IntVals[I], List1[I]);
+ EXPECT_EQ(StrVals[I], List2[I]);
+ }
+
Alias.removeArgument();
+ ListAlias.removeArgument();
}
TEST(CommandLineTest, ReadConfigFile) {