[llvm] [Support] Remove cl::bits (PR #226628)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 25 19:36:01 PDT 2026
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/226628
cl::list covers the same use, and cl::bits would block migration to
TableGen based representation.
LLM-aided
>From c3a5f39839a8306dbdfd2a3ee4939688d35d3016 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Fri, 25 Sep 2026 01:46:31 -0700
Subject: [PATCH] [Support] Remove cl::bits
cl::list covers the same use, and cl::bits would block migration to
TableGen based representation.
LLM-aided
---
llvm/docs/CommandLine.md | 66 ----------
llvm/include/llvm/Support/CommandLine.h | 145 ---------------------
llvm/unittests/Support/CommandLineTest.cpp | 15 +--
3 files changed, 5 insertions(+), 221 deletions(-)
diff --git a/llvm/docs/CommandLine.md b/llvm/docs/CommandLine.md
index fb3bccd242382..36f93501cd631 100644
--- a/llvm/docs/CommandLine.md
+++ b/llvm/docs/CommandLine.md
@@ -517,53 +517,6 @@ the list is simple, just like above. In this example, we used the
if the user does not specify any `.o` files on our command line. Again, this
just reduces the amount of checking we have to do.
-### Collecting options as a set of flags
-
-Instead of collecting sets of options in a list, it is also possible to gather
-information for enum values in a **bit vector**. The representation used by the
-{ref}`cl::bits <cl::bits>` class is an `unsigned` integer. An enum value is represented by a
-0/1 in the enum's ordinal value bit position. 1 indicating that the enum was
-specified, 0 otherwise. As each specified value is parsed, the resulting enum's
-bit is set in the option's bit vector:
-
-```cpp
-bits |= 1 << (unsigned)enum;
-```
-
-Options that are specified multiple times are redundant. Any instances after
-the first are discarded.
-
-Reworking the above list example, we could replace {ref}`cl::list <cl::list>` with {ref}`cl::bits <cl::bits>`:
-
-```cpp
-cl::bits<Opts> OptimizationBits(cl::desc("Available Optimizations:"),
- cl::values(
- clEnumVal(dce , "Dead Code Elimination"),
- clEnumVal(instsimplify , "Instruction Simplification"),
- clEnumValN(inlining, "inline", "Procedure Integration"),
- clEnumVal(strip , "Strip Symbols")));
-```
-
-To test to see if `instsimplify` was specified, we can use the `cl:bits::isSet`
-function:
-
-```cpp
-if (OptimizationBits.isSet(instsimplify)) {
- ...
-}
-```
-
-It's also possible to get the raw bit vector using the `cl::bits::getBits`
-function:
-
-```cpp
-unsigned bits = OptimizationBits.getBits();
-```
-
-Finally, if external storage is used, then the location specified must be of
-**type** `unsigned`. In all other ways a {ref}`cl::bits <cl::bits>` option is equivalent to a
-{ref}`cl::list <cl::list>` option.
-
(additional extra text)=
### Adding freeform text to help output
@@ -1324,25 +1277,6 @@ argument is the **type** of the external storage, not a boolean value. For this
class, the marker type '`bool`' is used to indicate that internal storage
should be used.
-(cl::bits)=
-
-#### The `cl::bits` class
-
-The `cl::bits` class is the class used to represent a list of command line
-options in the form of a bit vector. It is also a templated class which can
-take up to three arguments:
-
-```cpp
-namespace cl {
- template <class DataType, class Storage = bool,
- class ParserClass = parser<DataType> >
- class bits;
-}
-```
-
-This class works the exact same as the {ref}`cl::list <cl::list>` class, except that the second
-argument must be of **type** `unsigned` if external storage is used.
-
(cl::alias)=
#### The `cl::alias` class
diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h
index 63e25183ba376..fc79cbf476462 100644
--- a/llvm/include/llvm/Support/CommandLine.h
+++ b/llvm/include/llvm/Support/CommandLine.h
@@ -1782,151 +1782,6 @@ class list : public Option, public list_storage<DataType, StorageClass> {
std::function<void(const typename ParserClass::parser_data_type &)> Callback;
};
-//===----------------------------------------------------------------------===//
-// Default storage class definition: external storage. This implementation
-// assumes the user will specify a variable to store the data into with the
-// cl::location(x) modifier.
-//
-template <class DataType, class StorageClass> class bits_storage {
- unsigned *Location = nullptr; // Where to store the bits...
-
- template <class T> static unsigned Bit(const T &V) {
- unsigned BitPos = static_cast<unsigned>(V);
- assert(BitPos < sizeof(unsigned) * CHAR_BIT &&
- "enum exceeds width of bit vector!");
- return 1 << BitPos;
- }
-
-public:
- bits_storage() = default;
-
- bool setLocation(Option &O, unsigned &L) {
- if (Location)
- return O.error("cl::location(x) specified more than once!");
- Location = &L;
- return false;
- }
-
- template <class T> void addValue(const T &V) {
- assert(Location != nullptr &&
- "cl::location(...) not specified for a command "
- "line option with external storage!");
- *Location |= Bit(V);
- }
-
- unsigned getBits() { return *Location; }
-
- void clear() {
- if (Location)
- *Location = 0;
- }
-
- template <class T> bool isSet(const T &V) {
- return (*Location & Bit(V)) != 0;
- }
-};
-
-// Define how to hold bits. Since we can inherit from a class, we do so.
-// This makes us exactly compatible with the bits in all cases that it is used.
-//
-template <class DataType> class bits_storage<DataType, bool> {
- unsigned Bits{0}; // Where to store the bits...
-
- template <class T> static unsigned Bit(const T &V) {
- unsigned BitPos = static_cast<unsigned>(V);
- assert(BitPos < sizeof(unsigned) * CHAR_BIT &&
- "enum exceeds width of bit vector!");
- return 1 << BitPos;
- }
-
-public:
- template <class T> void addValue(const T &V) { Bits |= Bit(V); }
-
- unsigned getBits() { return Bits; }
-
- void clear() { Bits = 0; }
-
- template <class T> bool isSet(const T &V) { return (Bits & Bit(V)) != 0; }
-};
-
-//===----------------------------------------------------------------------===//
-// A bit vector of command options.
-//
-template <class DataType, class Storage = bool,
- class ParserClass = parser<DataType>>
-class bits : public Option, public bits_storage<DataType, Storage> {
- std::vector<unsigned> Positions;
- ParserClass Parser;
-
- enum ValueExpected getValueExpectedFlagDefault() const override {
- return Parser.getValueExpectedFlagDefault();
- }
-
- void getExtraOptionNames(SmallVectorImpl<StringRef> &OptionNames) override {
- return Parser.getExtraOptionNames(OptionNames);
- }
-
- bool handleOccurrence(unsigned pos, StringRef ArgName,
- StringRef Arg) override {
- typename ParserClass::parser_data_type Val =
- typename ParserClass::parser_data_type();
- if (Parser.parse(*this, ArgName, Arg, Val))
- return true; // Parse Error!
- this->addValue(Val);
- setPosition(pos);
- Positions.push_back(pos);
- if (Callback)
- Callback(Val);
- return false;
- }
-
- // Forward printing stuff to the parser...
- size_t getOptionWidth() const override {
- return Parser.getOptionWidth(*this);
- }
-
- void printOptionInfo(size_t GlobalWidth) const override {
- Parser.printOptionInfo(*this, GlobalWidth);
- }
-
- // Unimplemented: bits options don't currently store their default values.
- void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override {
- }
-
- void setDefault() override { bits_storage<DataType, Storage>::clear(); }
-
- void done() {
- addArgument();
- Parser.initialize();
- }
-
-public:
- // Command line options should not be copyable
- bits(const bits &) = delete;
- bits &operator=(const bits &) = delete;
-
- ParserClass &getParser() { return Parser; }
-
- unsigned getPosition(unsigned optnum) const {
- assert(optnum < this->size() && "Invalid option index");
- return Positions[optnum];
- }
-
- template <class... Mods>
- explicit bits(const Mods &... Ms)
- : Option(ZeroOrMore, NotHidden), Parser(*this) {
- apply(this, Ms...);
- done();
- }
-
- void setCallback(
- std::function<void(const typename ParserClass::parser_data_type &)> CB) {
- Callback = CB;
- }
-
- std::function<void(const typename ParserClass::parser_data_type &)> Callback;
-};
-
//===----------------------------------------------------------------------===//
// Aliased command line option (alias this name to a preexisting name)
//
diff --git a/llvm/unittests/Support/CommandLineTest.cpp b/llvm/unittests/Support/CommandLineTest.cpp
index 822b4637c6f64..e4b5bf4853610 100644
--- a/llvm/unittests/Support/CommandLineTest.cpp
+++ b/llvm/unittests/Support/CommandLineTest.cpp
@@ -1895,13 +1895,6 @@ TEST(CommandLineTest, Callback) {
cl::ResetAllOptionOccurrences();
}
-enum Enum { Val1, Val2 };
-static cl::bits<Enum> ExampleBits(
- cl::desc("An example cl::bits to ensure it compiles"),
- cl::values(
- clEnumValN(Val1, "bits-val1", "The Val1 value"),
- clEnumValN(Val1, "bits-val2", "The Val2 value")));
-
TEST(CommandLineTest, ConsumeAfterOnePositional) {
cl::ResetCommandLineParser();
@@ -2052,7 +2045,7 @@ TEST(CommandLineTest, ResetAllOptionOccurrences) {
StackOption<bool> Option("option");
StackOption<std::string> Str("str");
enum Vals { ValA, ValB, ValC };
- StackOption<Vals, cl::bits<Vals>> Bits(
+ StackOption<Vals, cl::list<Vals>> List(
cl::values(clEnumValN(ValA, "enableA", "Enable A"),
clEnumValN(ValB, "enableB", "Enable B"),
clEnumValN(ValC, "enableC", "Enable C")));
@@ -2069,7 +2062,9 @@ TEST(CommandLineTest, ResetAllOptionOccurrences) {
EXPECT_TRUE(Option);
EXPECT_EQ("STR", Str);
- EXPECT_EQ((1u << ValA) | (1u << ValC), Bits.getBits());
+ ASSERT_EQ(2u, List.size());
+ EXPECT_EQ(ValA, List[0]);
+ EXPECT_EQ(ValC, List[1]);
EXPECT_EQ("input", Input);
EXPECT_EQ(1u, ExtraArgs.size());
EXPECT_EQ("-arg", ExtraArgs[0]);
@@ -2077,7 +2072,7 @@ TEST(CommandLineTest, ResetAllOptionOccurrences) {
cl::ResetAllOptionOccurrences();
EXPECT_FALSE(Option);
EXPECT_EQ("", Str);
- EXPECT_EQ(0u, Bits.getBits());
+ EXPECT_TRUE(List.empty());
EXPECT_EQ(0, Input.getNumOccurrences());
EXPECT_EQ(0u, ExtraArgs.size());
}
More information about the llvm-commits
mailing list