Refactoring llvm command line parsing and option registration.
[oota-llvm.git] / include / llvm / Support / CommandLine.h
index 314dd951b2cbd099715822e8d9e6293f0c3f87c1..030907c1cf45595921f3300b6873d7e1d8ed1171 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef LLVM_SUPPORT_COMMANDLINE_H
 #define LLVM_SUPPORT_COMMANDLINE_H
 
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/Twine.h"
@@ -72,9 +73,6 @@ void AddExtraVersionPrinter(void (*func)());
 // (Currently not perfect, but best-effort.)
 void PrintOptionValues();
 
-// MarkOptionsChanged - Internal helper function.
-void MarkOptionsChanged();
-
 //===----------------------------------------------------------------------===//
 // Flags permitted to be passed to command line arguments
 //
@@ -191,13 +189,13 @@ class Option {
   unsigned Misc : 3;
   unsigned Position;       // Position of last occurrence of the option
   unsigned AdditionalVals; // Greater than 0 for multi-valued option.
-  Option *NextRegistered;  // Singly linked list of registered options.
 
 public:
   const char *ArgStr;   // The argument string itself (ex: "help", "o")
   const char *HelpStr;  // The descriptive text message for -help
   const char *ValueStr; // String describing what the value of this option is
   OptionCategory *Category; // The Category this option belongs to
+  bool FullyInitialized;    // Has addArguemnt been called?
 
   inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
     return (enum NumOccurrencesFlag)Occurrences;
@@ -221,7 +219,7 @@ public:
   //-------------------------------------------------------------------------===
   // Accessor functions set by OptionModifiers
   //
-  void setArgStr(const char *S) { ArgStr = S; }
+  void setArgStr(const char *S);
   void setDescription(const char *S) { HelpStr = S; }
   void setValueStr(const char *S) { ValueStr = S; }
   void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; }
@@ -237,8 +235,8 @@ protected:
                   enum OptionHidden Hidden)
       : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0),
         HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0),
-        AdditionalVals(0), NextRegistered(nullptr), ArgStr(""), HelpStr(""),
-        ValueStr(""), Category(&GeneralCategory) {}
+        AdditionalVals(0), ArgStr(""), HelpStr(""), ValueStr(""),
+        Category(&GeneralCategory), FullyInitialized(false) {}
 
   inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; }
 
@@ -253,8 +251,6 @@ public:
   /// For testing purposes only.
   void removeArgument();
 
-  Option *getNextRegisteredOption() const { return NextRegistered; }
-
   // Return the width of the option tag for printing...
   virtual size_t getOptionWidth() const = 0;
 
@@ -531,6 +527,8 @@ protected:
   };
 
 public:
+  generic_parser_base(Option &O) : Owner(O) {}
+
   virtual ~generic_parser_base() {} // Base class should have virtual-dtor
 
   // getNumOptions - Virtual function implemented by generic subclass to
@@ -569,18 +567,13 @@ public:
     printGenericOptionDiff(O, V, Default, GlobalWidth);
   }
 
-  void initialize(Option &O) {
-    // All of the modifiers for the option have been processed by now, so the
-    // argstr field should be stable, copy it down now.
-    //
-    hasArgStr = O.hasArgStr();
-  }
+  void initialize() {}
 
   void getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) {
     // If there has been no argstr specified, that means that we need to add an
     // argument for every possible option.  This ensures that our options are
     // vectored to us.
-    if (!hasArgStr)
+    if (!Owner.hasArgStr())
       for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
         OptionNames.push_back(getOption(i));
   }
@@ -597,7 +590,7 @@ public:
     //
     // If this is the case, we cannot allow a value.
     //
-    if (hasArgStr)
+    if (Owner.hasArgStr())
       return ValueRequired;
     else
       return ValueDisallowed;
@@ -609,7 +602,7 @@ public:
   unsigned findOption(const char *Name);
 
 protected:
-  bool hasArgStr;
+  Option &Owner;
 };
 
 // Default parser implementation - This implementation depends on having a
@@ -629,6 +622,7 @@ protected:
   SmallVector<OptionInfo, 8> Values;
 
 public:
+  parser(Option &O) : generic_parser_base(O) {}
   typedef DataType parser_data_type;
 
   // Implement virtual functions needed by generic_parser_base
@@ -646,7 +640,7 @@ public:
   // parse - Return true on error.
   bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) {
     StringRef ArgVal;
-    if (hasArgStr)
+    if (Owner.hasArgStr())
       ArgVal = Arg;
     else
       ArgVal = ArgName;
@@ -667,7 +661,7 @@ public:
     assert(findOption(Name) == Values.size() && "Option already exists!");
     OptionInfo X(Name, static_cast<DataType>(V), HelpStr);
     Values.push_back(X);
-    MarkOptionsChanged();
+    AddLiteralOption(Owner, Name);
   }
 
   /// removeLiteralOption - Remove the specified option.
@@ -684,6 +678,8 @@ public:
 //
 class basic_parser_impl { // non-template implementation of basic_parser<t>
 public:
+  basic_parser_impl(Option &O) {}
+
   virtual ~basic_parser_impl() {}
 
   enum ValueExpected getValueExpectedFlagDefault() const {
@@ -692,7 +688,7 @@ public:
 
   void getExtraOptionNames(SmallVectorImpl<const char *> &) {}
 
-  void initialize(Option &) {}
+  void initialize() {}
 
   // Return the width of the option tag for printing...
   size_t getOptionWidth(const Option &O) const;
@@ -722,6 +718,7 @@ protected:
 //
 template <class DataType> class basic_parser : public basic_parser_impl {
 public:
+  basic_parser(Option &O) : basic_parser_impl(O) {}
   typedef DataType parser_data_type;
   typedef OptionValue<DataType> OptVal;
 };
@@ -730,13 +727,13 @@ public:
 // parser<bool>
 //
 template <> class parser<bool> : public basic_parser<bool> {
-  const char *ArgStr;
-
 public:
+  parser(Option &O) : basic_parser(O) {}
+
   // parse - Return true on error.
   bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val);
 
-  template <class Opt> void initialize(Opt &O) { ArgStr = O.ArgStr; }
+  void initialize() {}
 
   enum ValueExpected getValueExpectedFlagDefault() const {
     return ValueOptional;
@@ -758,6 +755,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>);
 // parser<boolOrDefault>
 template <> class parser<boolOrDefault> : public basic_parser<boolOrDefault> {
 public:
+  parser(Option &O) : basic_parser(O) {}
+
   // parse - Return true on error.
   bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val);
 
@@ -782,6 +781,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>);
 //
 template <> class parser<int> : public basic_parser<int> {
 public:
+  parser(Option &O) : basic_parser(O) {}
+
   // parse - Return true on error.
   bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val);
 
@@ -802,6 +803,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<int>);
 //
 template <> class parser<unsigned> : public basic_parser<unsigned> {
 public:
+  parser(Option &O) : basic_parser(O) {}
+
   // parse - Return true on error.
   bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val);
 
@@ -823,6 +826,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned>);
 template <>
 class parser<unsigned long long> : public basic_parser<unsigned long long> {
 public:
+  parser(Option &O) : basic_parser(O) {}
+
   // parse - Return true on error.
   bool parse(Option &O, StringRef ArgName, StringRef Arg,
              unsigned long long &Val);
@@ -844,6 +849,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned long long>);
 //
 template <> class parser<double> : public basic_parser<double> {
 public:
+  parser(Option &O) : basic_parser(O) {}
+
   // parse - Return true on error.
   bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val);
 
@@ -864,6 +871,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<double>);
 //
 template <> class parser<float> : public basic_parser<float> {
 public:
+  parser(Option &O) : basic_parser(O) {}
+
   // parse - Return true on error.
   bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val);
 
@@ -884,6 +893,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<float>);
 //
 template <> class parser<std::string> : public basic_parser<std::string> {
 public:
+  parser(Option &O) : basic_parser(O) {}
+
   // parse - Return true on error.
   bool parse(Option &, StringRef, StringRef Arg, std::string &Value) {
     Value = Arg.str();
@@ -907,6 +918,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<std::string>);
 //
 template <> class parser<char> : public basic_parser<char> {
 public:
+  parser(Option &O) : basic_parser(O) {}
+
   // parse - Return true on error.
   bool parse(Option &, StringRef, StringRef Arg, char &Value) {
     Value = Arg[0];
@@ -1166,9 +1179,13 @@ class opt : public Option,
 
   void done() {
     addArgument();
-    Parser.initialize(*this);
+    Parser.initialize();
   }
 
+  // Command line options should not be copyable
+  opt(const opt &) LLVM_DELETED_FUNCTION;
+  opt &operator=(const opt &) LLVM_DELETED_FUNCTION;
+
 public:
   // setInitialValue - Used by the cl::init modifier...
   void setInitialValue(const DataType &V) { this->setValue(V, true); }
@@ -1183,7 +1200,7 @@ public:
   // One option...
   template <class M0t>
   explicit opt(const M0t &M0)
-      : Option(Optional, NotHidden) {
+      : Option(Optional, NotHidden), Parser(*this) {
     apply(M0, this);
     done();
   }
@@ -1191,7 +1208,7 @@ public:
   // Two options...
   template <class M0t, class M1t>
   opt(const M0t &M0, const M1t &M1)
-      : Option(Optional, NotHidden) {
+      : Option(Optional, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     done();
@@ -1200,7 +1217,7 @@ public:
   // Three options...
   template <class M0t, class M1t, class M2t>
   opt(const M0t &M0, const M1t &M1, const M2t &M2)
-      : Option(Optional, NotHidden) {
+      : Option(Optional, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1209,7 +1226,7 @@ public:
   // Four options...
   template <class M0t, class M1t, class M2t, class M3t>
   opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
-      : Option(Optional, NotHidden) {
+      : Option(Optional, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1219,7 +1236,7 @@ public:
   // Five options...
   template <class M0t, class M1t, class M2t, class M3t, class M4t>
   opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4)
-      : Option(Optional, NotHidden) {
+      : Option(Optional, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1231,7 +1248,7 @@ public:
   template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
   opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4,
       const M5t &M5)
-      : Option(Optional, NotHidden) {
+      : Option(Optional, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1245,7 +1262,7 @@ public:
             class M6t>
   opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4,
       const M5t &M5, const M6t &M6)
-      : Option(Optional, NotHidden) {
+      : Option(Optional, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1260,7 +1277,7 @@ public:
             class M6t, class M7t>
   opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4,
       const M5t &M5, const M6t &M6, const M7t &M7)
-      : Option(Optional, NotHidden) {
+      : Option(Optional, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1361,9 +1378,13 @@ class list : public Option, public list_storage<DataType, Storage> {
 
   void done() {
     addArgument();
-    Parser.initialize(*this);
+    Parser.initialize();
   }
 
+  // Command line options should not be copyable
+  list(const list &) LLVM_DELETED_FUNCTION;
+  list &operator=(const list &) LLVM_DELETED_FUNCTION;
+
 public:
   ParserClass &getParser() { return Parser; }
 
@@ -1377,14 +1398,14 @@ public:
   // One option...
   template <class M0t>
   explicit list(const M0t &M0)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     done();
   }
   // Two options...
   template <class M0t, class M1t>
   list(const M0t &M0, const M1t &M1)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     done();
@@ -1392,7 +1413,7 @@ public:
   // Three options...
   template <class M0t, class M1t, class M2t>
   list(const M0t &M0, const M1t &M1, const M2t &M2)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1401,7 +1422,7 @@ public:
   // Four options...
   template <class M0t, class M1t, class M2t, class M3t>
   list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1412,7 +1433,7 @@ public:
   template <class M0t, class M1t, class M2t, class M3t, class M4t>
   list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
        const M4t &M4)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1424,7 +1445,7 @@ public:
   template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
   list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
        const M4t &M4, const M5t &M5)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1438,7 +1459,7 @@ public:
             class M6t>
   list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
        const M4t &M4, const M5t &M5, const M6t &M6)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1453,7 +1474,7 @@ public:
             class M6t, class M7t>
   list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
        const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1581,9 +1602,13 @@ class bits : public Option, public bits_storage<DataType, Storage> {
 
   void done() {
     addArgument();
-    Parser.initialize(*this);
+    Parser.initialize();
   }
 
+  // Command line options should not be copyable
+  bits(const bits &) LLVM_DELETED_FUNCTION;
+  bits &operator=(const bits &) LLVM_DELETED_FUNCTION;
+
 public:
   ParserClass &getParser() { return Parser; }
 
@@ -1595,14 +1620,14 @@ public:
   // One option...
   template <class M0t>
   explicit bits(const M0t &M0)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     done();
   }
   // Two options...
   template <class M0t, class M1t>
   bits(const M0t &M0, const M1t &M1)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     done();
@@ -1610,7 +1635,7 @@ public:
   // Three options...
   template <class M0t, class M1t, class M2t>
   bits(const M0t &M0, const M1t &M1, const M2t &M2)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1619,7 +1644,7 @@ public:
   // Four options...
   template <class M0t, class M1t, class M2t, class M3t>
   bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1630,7 +1655,7 @@ public:
   template <class M0t, class M1t, class M2t, class M3t, class M4t>
   bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
        const M4t &M4)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1642,7 +1667,7 @@ public:
   template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t>
   bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
        const M4t &M4, const M5t &M5)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1656,7 +1681,7 @@ public:
             class M6t>
   bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
        const M4t &M4, const M5t &M5, const M6t &M6)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1671,7 +1696,7 @@ public:
             class M6t, class M7t>
   bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3,
        const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7)
-      : Option(ZeroOrMore, NotHidden) {
+      : Option(ZeroOrMore, NotHidden), Parser(*this) {
     apply(M0, this);
     apply(M1, this);
     apply(M2, this);
@@ -1718,6 +1743,10 @@ class alias : public Option {
     addArgument();
   }
 
+  // Command line options should not be copyable
+  alias(const alias &) LLVM_DELETED_FUNCTION;
+  alias &operator=(const alias &) LLVM_DELETED_FUNCTION;
+
 public:
   void setAliasFor(Option &O) {
     if (AliasFor)
@@ -1795,9 +1824,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
 /// \brief Use this to get a StringMap to all registered named options
 /// (e.g. -help). Note \p Map Should be an empty StringMap.
 ///
-/// \param [out] Map will be filled with mappings where the key is the
-/// Option argument string (e.g. "help") and value is the corresponding
-/// Option*.
+/// \return A reference to the StringMap used by the cl APIs to parse options.
 ///
 /// Access to unnamed arguments (i.e. positional) are not provided because
 /// it is expected that the client already has access to these.
@@ -1805,8 +1832,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
 /// Typical usage:
 /// \code
 /// main(int argc,char* argv[]) {
-/// StringMap<llvm::cl::Option*> opts;
-/// llvm::cl::getRegisteredOptions(opts);
+/// StringMap<llvm::cl::Option*> &opts = llvm::cl::getRegisteredOptions();
 /// assert(opts.count("help") == 1)
 /// opts["help"]->setDescription("Show alphabetical help information")
 /// // More code
@@ -1818,7 +1844,11 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
 /// This interface is useful for modifying options in libraries that are out of
 /// the control of the client. The options should be modified before calling
 /// llvm::cl::ParseCommandLineOptions().
-void getRegisteredOptions(StringMap<Option *> &Map);
+///
+/// Hopefully this API can be depricated soon. Any situation where options need
+/// to be modified by tools or libraries should be handled by sane APIs rather
+/// than just handing around a global list.
+StringMap<Option *> &getRegisteredOptions();
 
 //===----------------------------------------------------------------------===//
 // Standalone command line processing utilities.
@@ -1898,6 +1928,24 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
 /// option category to display in the -help output.
 void HideUnrelatedOptions(cl::OptionCategory &Category);
 
+/// \brief Mark all options not part of the categories as cl::ReallyHidden.
+///
+/// \param Categories the categories of options to keep displaying.
+///
+/// Some tools (like clang-format) like to be able to hide all options that are
+/// not specific to the tool. This function allows a tool to specify a single
+/// option category to display in the -help output.
+void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories);
+
+/// \brief Adds a new option for parsing and provides the option it refers to.
+///
+/// \param O pointer to the option
+/// \param Name the string name for the option to handle during parsing
+///
+/// Literal options are used by some parsers to register special option values.
+/// This is how the PassNameParser registers pass names for opt.
+void AddLiteralOption(Option &O, const char *Name);
+
 } // End namespace cl
 
 } // End namespace llvm