<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Courier;
        panose-1:2 7 4 9 2 2 5 2 4 4;}
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}
@font-face
        {font-family:LucidaGrande;}
@font-face
        {font-family:Courier-Bold;}
@font-face
        {font-family:LucidaGrande-Bold;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.EmailStyle19
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal">I didn’t see a response. But I fixed this in our downstream code and it is working now as expected. It fixes two issues (1) clearing cl::bits and (2) allowing an optional storage location for cl::bits (the reinterpret_cast is wrong for
 an enum to unsigned cast; it should be a static_cast). If there is interest in fixing this upstream, I can send the following patch for review (note, the following is for our downstream branch but I can put together a patch for master along with some unit
 tests that expose the issue). <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span style="font-family:Consolas">diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">index 05374e3..712d6d3 100644<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">--- a/llvm/include/llvm/Support/CommandLine.h<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">+++ b/llvm/include/llvm/Support/CommandLine.h<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">@@ -1720,7 +1720,7 @@ template <class DataType, class StorageClass> class bits_storage {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">   unsigned *Location = nullptr; // Where to store the bits...<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">   template <class T> static unsigned Bit(const T &V) {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">-    unsigned BitPos = reinterpret_cast<unsigned>(V);<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">+    unsigned BitPos = static_cast<unsigned>(V);<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">     assert(BitPos < sizeof(unsigned) * CHAR_BIT &&<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">            "enum exceeds width of bit vector!");<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">     return 1 << BitPos;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">@@ -1744,6 +1744,11 @@ public:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">   unsigned getBits() { return *Location; }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">+  void clear() {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">+    if (Location)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">+      *Location = 0;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">+  }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">+<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">   template <class T> bool isSet(const T &V) {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">     return (*Location & Bit(V)) != 0;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">   }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">@@ -1767,6 +1772,8 @@ public:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">   unsigned getBits() { return Bits; }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">+  void clear() { Bits = 0; }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">+<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">   template <class T> bool isSet(const T &V) { return (Bits & Bit(V)) != 0; }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">};<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">@@ -1813,7 +1820,7 @@ class bits : public Option, public bits_storage<DataType, Storage> {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">   void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">   }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">-  void setDefault() override {}<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">+  void setDefault() override { bits_storage<DataType, Storage>::clear(); }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">   void done() {<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">     addArgument();<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b>From:</b> Riyaz Puthiyapurayil <br>
<b>Sent:</b> Sunday, March 21, 2021 4:30 PM<br>
<b>To:</b> llvm-dev@lists.llvm.org<br>
<b>Subject:</b> CommandLine -- ResetAllOptionOccurrences with cl::bits -- Bug or by design?<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I have some unit tests where I want to parse different command lines where some options use
<span style="font-family:Consolas">cl::bits</span> with an enum type. I want to reset the option occurrences in each unit test and reinvoke the command line parser with a new command line. While
<span style="font-family:Consolas">ResetAllOptionOccurrences</span> resets every other kind of option, it doesn’t do so for cl::bits. Is this by design?<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I see <span style="font-family:Consolas">setDefaultValue</span> of
<span style="font-family:Consolas">cl::bits</span> is an empty function. Why doesn’t it set the internal bit storage to 0 when ResetAllOptionOccurrences is called? I thought I could instead use an external storage and set that to 0. But that doesn’t work either.
 It results in an error:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span style="font-family:Consolas">unsigned MyOptStorage;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">static llvm::cl::bits<MyOpt,
<b>unsigned</b>> MyOpts(<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">….<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">      llvm::cl::location(MyOptStorage),<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">…);<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span style="font-family:Consolas">include/llvm/Support/CommandLine.h:1723:23: error: reinterpret_cast from 'MyOpt’ to 'unsigned int' is not allowed<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:Consolas">    unsigned BitPos = reinterpret_cast<unsigned>(V);<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">where ‘<span style="font-family:Consolas">MyOpt</span>’ is an enum type.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">So how does one specify <span style="font-family:Consolas">cl::bits</span> with an external storage location if DataType is an enum? There is not much information in Command Line Reference Manual. Note that I used
<b>unsigned</b> above just like the excerpt from the manual says:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:14.0pt;font-family:LucidaGrande">The
</span><span style="font-size:13.0pt;font-family:Courier">cl::bits</span><span style="font-size:14.0pt;font-family:LucidaGrande"> 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:<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><b><span style="font-size:13.0pt;font-family:Courier-Bold;color:#0D5F18">namespace</span></b><span style="font-size:13.0pt;font-family:Courier"> cl {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:13.0pt;font-family:Courier"> 
</span><b><span style="font-size:13.0pt;font-family:Courier-Bold;color:#0D5F18">template</span></b><span style="font-size:13.0pt;font-family:Courier">
<span style="color:#535353"><</span></span><b><span style="font-size:13.0pt;font-family:Courier-Bold;color:#0D5F18">class</span></b><span style="font-size:13.0pt;font-family:Courier">
</span><b><span style="font-size:13.0pt;font-family:Courier-Bold;color:#1370A6">DataType</span></b><span style="font-size:13.0pt;font-family:Courier">,
</span><b><span style="font-size:13.0pt;font-family:Courier-Bold;color:#0D5F18">class</span></b><span style="font-size:13.0pt;font-family:Courier">
</span><b><span style="font-size:13.0pt;font-family:Courier-Bold;color:#1370A6">Storage</span></b><span style="font-size:13.0pt;font-family:Courier">
<span style="color:#535353">=</span> <span style="color:#7C1302">bool</span>,<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:13.0pt;font-family:Courier">           
</span><b><span style="font-size:13.0pt;font-family:Courier-Bold;color:#0D5F18">class</span></b><span style="font-size:13.0pt;font-family:Courier">
</span><b><span style="font-size:13.0pt;font-family:Courier-Bold;color:#1370A6">ParserClass</span></b><span style="font-size:13.0pt;font-family:Courier">
<span style="color:#535353">=</span> parser<span style="color:#535353"><</span>DataType<span style="color:#535353">></span>
<span style="color:#535353">></span><o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:13.0pt;font-family:Courier"> 
</span><b><span style="font-size:13.0pt;font-family:Courier-Bold;color:#0D5F18">class</span></b><span style="font-size:13.0pt;font-family:Courier">
</span><b><span style="font-size:13.0pt;font-family:Courier-Bold;color:#1370A6">bits</span></b><span style="font-size:13.0pt;font-family:Courier">;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:13.0pt;font-family:Courier">}<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:14.0pt;font-family:LucidaGrande">This class works the exact same as the
<u><span style="color:#BD6505">cl::list</span></u> class, except that the second argument must be of
</span><b><span style="font-size:14.0pt;font-family:LucidaGrande-Bold">type</span></b><span style="font-size:14.0pt;font-family:LucidaGrande">
</span><span style="font-size:13.0pt;font-family:Courier">unsigned</span><span style="font-size:14.0pt;font-family:LucidaGrande"> if external storage is used.</span><o:p></o:p></p>
</div>
</body>
</html>