Improve -fno-opt style option processing to not require an extra

option to make the -fno- form on the option.  We also document the new
form in the CommandLine documentation.

llvm-svn: 63559
This commit is contained in:
Mike Stump 2009-02-02 22:48:49 +00:00
parent 4eda2cbe5f
commit b92f839f9c
3 changed files with 42 additions and 54 deletions

View File

@ -1447,6 +1447,16 @@ unrecognized option strings to it as values instead of signaling an
error. As with <b><tt>cl::CommaSeparated</tt></b></a>, this modifier
only makes sense with a <a href="#cl::list">cl::list</a> option.</li>
<li><a name="cl::AllowInverse">The <b><tt>cl::AllowInverse</tt></b></a>
modifier can be used on options that have the form <tt>-fopt</tt> to
automatically create a corresponding
<tt>-fno-opt</tt> option. The <tt>f</tt> can be any single
character, and the <tt>opt</tt> can be any one or more characters.
The value of the created option is the logical complement of the value
that would have been used if the base form of the option was used.
This modifier only makes sense with an option that uses
a <a href="#boolparser">bool parser</a>.</li>
</ul>
@ -1745,7 +1755,11 @@ for any data type.</li>
<li><a name="boolparser">The <b><tt>parser&lt;bool&gt;</tt> specialization</b></a>
is used to convert boolean strings to a boolean value. Currently accepted
strings are "<tt>true</tt>", "<tt>TRUE</tt>", "<tt>True</tt>", "<tt>1</tt>",
"<tt>false</tt>", "<tt>FALSE</tt>", "<tt>False</tt>", and "<tt>0</tt>".</li>
"<tt>false</tt>", "<tt>FALSE</tt>", "<tt>False</tt>", and "<tt>0</tt>". The
<b><tt>cl::AllowInverse</tt></b> modifier can be used on an option of the form
<tt>-fopt</tt> that uses the <tt>parser&lt;bool&gt;</tt> specialization
to create a corresponding option with the form <tt>-fno-opt</tt>. See
<a href="#cl::AllowInverse"><tt>cl::AllowInverse</tt></a> for details.</li>
<li><a name="boolOrDefaultparser">The <b><tt>parser&lt;boolOrDefault&gt;</tt>
specialization</b></a> is used for cases where the value is boolean,

View File

@ -126,7 +126,8 @@ enum MiscFlags { // Miscellaneous flags to adjust argument
CommaSeparated = 0x200, // Should this cl::list split between commas?
PositionalEatsArgs = 0x400, // Should this positional cl::list eat -args?
Sink = 0x800, // Should this cl::list eat all unknown options?
MiscMask = 0xE00 // Union of the above flags.
AllowInverse = 0x1000, // Can this option take a -Xno- form?
MiscMask = 0x1E00 // Union of the above flags.
};
@ -302,12 +303,6 @@ struct LocationClass {
template<class Ty>
LocationClass<Ty> location(Ty &L) { return LocationClass<Ty>(L); }
// opposite_of - Allow the user to specify which other option this
// option is the opposite of.
//
template<class Ty>
LocationClass<bool> opposite_of(Ty &O) { return location(O.getValue()); }
//===----------------------------------------------------------------------===//
// Enum valued command line option
@ -542,10 +537,33 @@ struct basic_parser : public basic_parser_impl {
//
template<>
class parser<bool> : public basic_parser<bool> {
bool IsInvertable; // Should we synthezise a -xno- style option?
const char *ArgStr;
public:
void getExtraOptionNames(std::vector<const char*> &OptionNames) {
if (IsInvertable) {
char *s = new char [strlen(ArgStr) + 3 + 1];
s[0] = ArgStr[0];
s[1] = 'n';
s[2] = 'o';
s[3] = '-';
strcpy(&s[4], ArgStr+1);
OptionNames.push_back(s);
}
}
// parse - Return true on error.
bool parse(Option &O, const char *ArgName, const std::string &Arg, bool &Val);
template <class Opt>
void initialize(Opt &O) {
if (O.getMiscFlags() & llvm::cl::AllowInverse)
IsInvertable = true;
else
IsInvertable = false;
ArgStr = O.ArgStr;
}
enum ValueExpected getValueExpectedFlagDefault() const {
return ValueOptional;
}
@ -582,30 +600,6 @@ public:
EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>);
//--------------------------------------------------
// parser<boolInverse>
class boolInverse { };
template<>
class parser<boolInverse> : public basic_parser<bool> {
public:
typedef bool parser_data_type;
// parse - Return true on error.
bool parse(Option &O, const char *ArgName, const std::string &Arg,
bool &Val);
enum ValueExpected getValueExpectedFlagDefault() const {
return ValueOptional;
}
// getValueName - Do not print =<value> at all.
virtual const char *getValueName() const { return 0; }
// An out-of-line virtual method to provide a 'home' for this class.
virtual void anchor();
};
EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>);
//--------------------------------------------------
// parser<int>
//
@ -947,9 +941,6 @@ EXTERN_TEMPLATE_INSTANTIATION(class opt<int>);
EXTERN_TEMPLATE_INSTANTIATION(class opt<std::string>);
EXTERN_TEMPLATE_INSTANTIATION(class opt<bool>);
class boolInverse;
typedef opt<bool, true, parser<boolInverse> > inverse_opt;
//===----------------------------------------------------------------------===//
// list_storage class

View File

@ -40,7 +40,6 @@ using namespace cl;
//
TEMPLATE_INSTANTIATION(class basic_parser<bool>);
TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>);
TEMPLATE_INSTANTIATION(class basic_parser<boolInverse>);
TEMPLATE_INSTANTIATION(class basic_parser<int>);
TEMPLATE_INSTANTIATION(class basic_parser<unsigned>);
TEMPLATE_INSTANTIATION(class basic_parser<double>);
@ -56,7 +55,6 @@ void Option::anchor() {}
void basic_parser_impl::anchor() {}
void parser<bool>::anchor() {}
void parser<boolOrDefault>::anchor() {}
void parser<boolInverse>::anchor() {}
void parser<int>::anchor() {}
void parser<unsigned>::anchor() {}
void parser<double>::anchor() {}
@ -874,6 +872,8 @@ bool parser<bool>::parse(Option &O, const char *ArgName,
return O.error(": '" + Arg +
"' is invalid value for boolean argument! Try 0 or 1");
}
if (IsInvertable && strncmp(ArgName+1, "no-", 3) == 0)
Value = !Value;
return false;
}
@ -894,23 +894,6 @@ bool parser<boolOrDefault>::parse(Option &O, const char *ArgName,
return false;
}
// parser<boolInverse> implementation
//
bool parser<boolInverse>::parse(Option &O, const char *ArgName,
const std::string &Arg, bool &Value) {
if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||
Arg == "1") {
Value = false;
} else if (Arg == "false" || Arg == "FALSE"
|| Arg == "False" || Arg == "0") {
Value = true;
} else {
return O.error(": '" + Arg +
"' is invalid value for boolean argument! Try 0 or 1");
}
return false;
}
// parser<int> implementation
//
bool parser<int>::parse(Option &O, const char *ArgName,