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 @@ -1694,7 +1694,7 @@ unsigned *Location = nullptr; // Where to store the bits... template static unsigned Bit(const T &V) { - unsigned BitPos = reinterpret_cast(V); + unsigned BitPos = static_cast(V); assert(BitPos < sizeof(unsigned) * CHAR_BIT && "enum exceeds width of bit vector!"); return 1 << BitPos; @@ -1719,6 +1719,11 @@ unsigned getBits() { return *Location; } + void clear() { + if (Location) + *Location = 0; + } + template bool isSet(const T &V) { return (*Location & Bit(V)) != 0; } @@ -1728,10 +1733,10 @@ // This makes us exactly compatible with the bits in all cases that it is used. // template class bits_storage { - unsigned Bits; // Where to store the bits... + unsigned Bits{0}; // Where to store the bits... template static unsigned Bit(const T &V) { - unsigned BitPos = (unsigned)V; + unsigned BitPos = static_cast(V); assert(BitPos < sizeof(unsigned) * CHAR_BIT && "enum exceeds width of bit vector!"); return 1 << BitPos; @@ -1742,6 +1747,8 @@ unsigned getBits() { return Bits; } + void clear() { Bits = 0; } + template bool isSet(const T &V) { return (Bits & Bit(V)) != 0; } }; @@ -1788,7 +1795,7 @@ void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { } - void setDefault() override {} + void setDefault() override { bits_storage::clear(); } void done() { addArgument(); 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 @@ -1931,20 +1931,27 @@ TEST(CommandLineTest, ResetAllOptionOccurrences) { cl::ResetCommandLineParser(); - // -option [sink] input [args] + // -option -enableA -enableC [sink] input [args] StackOption Option("option"); + enum Vals { ValA, ValB, ValC }; + StackOption> Bits( + cl::values(clEnumValN(ValA, "enableA", "Enable A"), + clEnumValN(ValB, "enableB", "Enable B"), + clEnumValN(ValC, "enableC", "Enable C"))); StackOption> Sink(cl::Sink); StackOption Input(cl::Positional); StackOption> ExtraArgs(cl::ConsumeAfter); - const char *Args[] = {"prog", "-option", "-unknown", "input", "-arg"}; + const char *Args[] = {"prog", "-option", "-enableA", "-enableC", + "-unknown", "input", "-arg"}; std::string Errs; raw_string_ostream OS(Errs); - EXPECT_TRUE(cl::ParseCommandLineOptions(5, Args, StringRef(), &OS)); + EXPECT_TRUE(cl::ParseCommandLineOptions(7, Args, StringRef(), &OS)); EXPECT_TRUE(OS.str().empty()); EXPECT_TRUE(Option); + EXPECT_EQ((1u << ValA) | (1u << ValC), Bits.getBits()); EXPECT_EQ(1u, Sink.size()); EXPECT_EQ("-unknown", Sink[0]); EXPECT_EQ("input", Input); @@ -1953,6 +1960,7 @@ cl::ResetAllOptionOccurrences(); EXPECT_FALSE(Option); + EXPECT_EQ(0u, Bits.getBits()); EXPECT_EQ(0u, Sink.size()); EXPECT_EQ(0, Input.getNumOccurrences()); EXPECT_EQ(0u, ExtraArgs.size());