Make it not an error to specify -O* options several times.

As in 'llvmc -O2 -O2 test.c'.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97787 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov 2010-03-05 04:46:39 +00:00
parent 0d61349dc3
commit b5c4239606
4 changed files with 76 additions and 31 deletions

View File

@ -45,6 +45,7 @@ def hidden;
def init;
def multi_val;
def one_or_more;
def zero_or_more;
def optional;
def really_hidden;
def required;

View File

@ -329,16 +329,22 @@ separate option groups syntactically.
- ``required`` - this option must be specified exactly once (or, in case of
the list options without the ``multi_val`` property, at least
once). Incompatible with ``zero_or_one`` and ``one_or_more``.
once). Incompatible with ``optional`` and ``one_or_more``.
- ``one_or_more`` - the option must be specified at least one time. Useful
only for list options in conjunction with ``multi_val``; for ordinary lists
it is synonymous with ``required``. Incompatible with ``required`` and
``zero_or_one``.
- ``optional`` - the option can be specified either zero times or exactly
once. The default for switch options. Useful only for list options in
conjunction with ``multi_val``. Incompatible with ``required``,
``zero_or_more`` and ``one_or_more``.
- ``optional`` - the option can be specified zero or one times. Useful only
for list options in conjunction with ``multi_val``. Incompatible with
``required`` and ``one_or_more``.
- ``one_or_more`` - the option must be specified at least once. Can be useful
to allow switch options be both obligatory and be specified multiple
times. For list options is useful only in conjunction with ``multi_val``;
for ordinary it is synonymous with ``required``. Incompatible with
``required``, ``optional`` and ``zero_or_more``.
- ``zero_or_more`` - the option can be specified zero or more times. Useful
to allow a single switch option to be specified more than
once. Incompatible with ``required``, ``optional`` and ``one_or_more``.
- ``hidden`` - the description of this option will not appear in
the ``--help`` output (but will appear in the ``--help-hidden``

View File

@ -25,13 +25,13 @@ def OptList : OptionList<[
(switch_option "opt",
(help "Enable opt")),
(switch_option "O0",
(help "Turn off optimization")),
(help "Turn off optimization"), (zero_or_more)),
(switch_option "O1",
(help "Optimization level 1")),
(help "Optimization level 1"), (zero_or_more)),
(switch_option "O2",
(help "Optimization level 2")),
(help "Optimization level 2"), (zero_or_more)),
(switch_option "O3",
(help "Optimization level 3")),
(help "Optimization level 3"), (zero_or_more)),
(switch_option "S",
(help "Stop after compilation, do not assemble")),
(switch_option "c",

View File

@ -230,7 +230,8 @@ namespace OptionDescriptionFlags {
enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
ReallyHidden = 0x4, Extern = 0x8,
OneOrMore = 0x10, Optional = 0x20,
CommaSeparated = 0x40, ForwardNotSplit = 0x80 };
CommaSeparated = 0x40, ForwardNotSplit = 0x80,
ZeroOrMore = 0x100 };
}
/// OptionDescription - Represents data contained in a single
@ -260,6 +261,9 @@ struct OptionDescription {
/// Merge - Merge two option descriptions.
void Merge (const OptionDescription& other);
/// CheckConsistency - Check that the flags are consistent.
void CheckConsistency() const;
// Misc convenient getters/setters.
bool isAlias() const;
@ -281,6 +285,9 @@ struct OptionDescription {
bool isOneOrMore() const;
void setOneOrMore();
bool isZeroOrMore() const;
void setZeroOrMore();
bool isOptional() const;
void setOptional();
@ -301,6 +308,20 @@ struct OptionDescription {
};
void OptionDescription::CheckConsistency() const {
unsigned i = 0;
i += this->isRequired();
i += this->isOptional();
i += this->isOneOrMore();
i += this->isZeroOrMore();
if (i > 1) {
throw "Only one of (required), (optional), (one_or_more) or "
"(zero_or_more) properties is allowed!";
}
}
void OptionDescription::Merge (const OptionDescription& other)
{
if (other.Type != Type)
@ -359,6 +380,13 @@ void OptionDescription::setOneOrMore() {
Flags |= OptionDescriptionFlags::OneOrMore;
}
bool OptionDescription::isZeroOrMore() const {
return Flags & OptionDescriptionFlags::ZeroOrMore;
}
void OptionDescription::setZeroOrMore() {
Flags |= OptionDescriptionFlags::ZeroOrMore;
}
bool OptionDescription::isOptional() const {
return Flags & OptionDescriptionFlags::Optional;
}
@ -593,6 +621,7 @@ public:
AddHandler("init", &CollectOptionProperties::onInit);
AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore);
AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
AddHandler("required", &CollectOptionProperties::onRequired);
AddHandler("optional", &CollectOptionProperties::onOptional);
@ -651,10 +680,9 @@ private:
void onRequired (const DagInit& d) {
CheckNumberOfArguments(d, 0);
if (optDesc_.isOneOrMore() || optDesc_.isOptional())
throw "Only one of (required), (optional) or "
"(one_or_more) properties is allowed!";
optDesc_.setRequired();
optDesc_.CheckConsistency();
}
void onInit (const DagInit& d) {
@ -673,24 +701,31 @@ private:
void onOneOrMore (const DagInit& d) {
CheckNumberOfArguments(d, 0);
if (optDesc_.isRequired() || optDesc_.isOptional())
throw "Only one of (required), (optional) or "
"(one_or_more) properties is allowed!";
if (!OptionType::IsList(optDesc_.Type))
llvm::errs() << "Warning: specifying the 'one_or_more' property "
"on a non-list option will have no effect.\n";
optDesc_.setOneOrMore();
optDesc_.CheckConsistency();
}
void onZeroOrMore (const DagInit& d) {
CheckNumberOfArguments(d, 0);
if (OptionType::IsList(optDesc_.Type))
llvm::errs() << "Warning: specifying the 'zero_or_more' property "
"on a list option has no effect.\n";
optDesc_.setZeroOrMore();
optDesc_.CheckConsistency();
}
void onOptional (const DagInit& d) {
CheckNumberOfArguments(d, 0);
if (optDesc_.isRequired() || optDesc_.isOneOrMore())
throw "Only one of (required), (optional) or "
"(one_or_more) properties is allowed!";
if (!OptionType::IsList(optDesc_.Type))
llvm::errs() << "Warning: specifying the 'optional' property"
"on a non-list option will have no effect.\n";
"on a non-list option has no effect.\n";
optDesc_.setOptional();
optDesc_.CheckConsistency();
}
void onMultiVal (const DagInit& d) {
@ -2323,12 +2358,15 @@ void EmitOptionDefinitions (const OptionDescriptions& descs,
else
O << ", cl::Required";
}
else if (val.isOneOrMore() && val.isList()) {
O << ", cl::OneOrMore";
}
else if (val.isOptional() && val.isList()) {
if (val.isOptional())
O << ", cl::Optional";
}
if (val.isOneOrMore())
O << ", cl::OneOrMore";
if (val.isZeroOrMore())
O << ", cl::ZeroOrMore";
if (val.isReallyHidden())
O << ", cl::ReallyHidden";