* Fix assertion failure caused by command line argument getting removed after

the map was freed.
* Cleanup code a bit


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3121 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2002-07-29 20:58:42 +00:00
parent 2c04779ba7
commit e8e258b1a7
2 changed files with 70 additions and 30 deletions

View File

@ -29,9 +29,16 @@ using std::cerr;
// Return the global command line option vector. Making it a function scoped // Return the global command line option vector. Making it a function scoped
// static ensures that it will be initialized correctly before its first use. // static ensures that it will be initialized correctly before its first use.
// //
static map<string,Option*> *CommandLineOptions = 0;
static map<string, Option*> &getOpts() { static map<string, Option*> &getOpts() {
static map<string,Option*> CommandLineOptions; if (CommandLineOptions == 0) CommandLineOptions = new map<string,Option*>();
return CommandLineOptions; return *CommandLineOptions;
}
static Option *getOption(const string &Str) {
if (CommandLineOptions == 0) return 0;
map<string,Option*>::iterator I = CommandLineOptions->find(Str);
return I != CommandLineOptions->end() ? I->second : 0;
} }
static vector<Option*> &getPositionalOpts() { static vector<Option*> &getPositionalOpts() {
@ -39,13 +46,26 @@ static vector<Option*> &getPositionalOpts() {
return Positional; return Positional;
} }
static void AddArgument(const string &ArgName, Option *Opt) { static void AddArgument(const char *ArgName, Option *Opt) {
if (getOpts().find(ArgName) != getOpts().end()) { if (getOption(ArgName)) {
cerr << "CommandLine Error: Argument '" << ArgName cerr << "CommandLine Error: Argument '" << ArgName
<< "' defined more than once!\n"; << "' defined more than once!\n";
} else { } else {
// Add argument to the argument map! // Add argument to the argument map!
getOpts().insert(std::make_pair(ArgName, Opt)); getOpts()[ArgName] = Opt;
}
}
// RemoveArgument - It's possible that the argument is no longer in the map if
// options have already been processed and the map has been deleted!
//
static void RemoveArgument(const char *ArgName, Option *Opt) {
if (CommandLineOptions == 0) return;
assert(getOption(ArgName) == Opt && "Arg not in map!");
CommandLineOptions->erase(ArgName);
if (CommandLineOptions->empty()) {
delete CommandLineOptions;
CommandLineOptions = 0;
} }
} }
@ -103,25 +123,25 @@ static inline bool isPrefixedOrGrouping(const Option *O) {
static Option *getOptionPred(std::string Name, unsigned &Length, static Option *getOptionPred(std::string Name, unsigned &Length,
bool (*Pred)(const Option*)) { bool (*Pred)(const Option*)) {
map<string, Option*>::iterator I = getOpts().find(Name); Option *Op = getOption(Name);
if (I != getOpts().end() && Pred(I->second)) { if (Op && Pred(Op)) {
Length = Name.length(); Length = Name.length();
return I->second; return Op;
} }
if (Name.size() == 1) return 0; if (Name.size() == 1) return 0;
do { do {
Name.erase(Name.end()-1, Name.end()); // Chop off the last character... Name.erase(Name.end()-1, Name.end()); // Chop off the last character...
I = getOpts().find(Name); Op = getOption(Name);
// Loop while we haven't found an option and Name still has at least two // Loop while we haven't found an option and Name still has at least two
// characters in it (so that the next iteration will not be the empty // characters in it (so that the next iteration will not be the empty
// string... // string...
} while ((I == getOpts().end() || !Pred(I->second)) && Name.size() > 1); } while ((Op == 0 || !Pred(Op)) && Name.size() > 1);
if (I != getOpts().end() && Pred(I->second)) { if (Op && Pred(Op)) {
Length = Name.length(); Length = Name.length();
return I->second; // Found one! return Op; // Found one!
} }
return 0; // No option found! return 0; // No option found!
} }
@ -384,7 +404,8 @@ void cl::ParseCommandLineOptions(int &argc, char **argv,
// Free all of the memory allocated to the map. Command line options may only // Free all of the memory allocated to the map. Command line options may only
// be processed once! // be processed once!
Opts.clear(); delete CommandLineOptions;
CommandLineOptions = 0;
PositionalOpts.clear(); PositionalOpts.clear();
// If we had an error processing our arguments, don't let the program execute // If we had an error processing our arguments, don't let the program execute
@ -445,8 +466,7 @@ void Option::addArgument(const char *ArgStr) {
void Option::removeArgument(const char *ArgStr) { void Option::removeArgument(const char *ArgStr) {
if (ArgStr[0]) { if (ArgStr[0]) {
assert(getOpts()[ArgStr] == this && "Arg not in map!"); RemoveArgument(ArgStr, this);
getOpts().erase(ArgStr);
} else if (getFormattingFlag() == Positional) { } else if (getFormattingFlag() == Positional) {
vector<Option*>::iterator I = vector<Option*>::iterator I =
std::find(getPositionalOpts().begin(), getPositionalOpts().end(), this); std::find(getPositionalOpts().begin(), getPositionalOpts().end(), this);

View File

@ -29,9 +29,16 @@ using std::cerr;
// Return the global command line option vector. Making it a function scoped // Return the global command line option vector. Making it a function scoped
// static ensures that it will be initialized correctly before its first use. // static ensures that it will be initialized correctly before its first use.
// //
static map<string,Option*> *CommandLineOptions = 0;
static map<string, Option*> &getOpts() { static map<string, Option*> &getOpts() {
static map<string,Option*> CommandLineOptions; if (CommandLineOptions == 0) CommandLineOptions = new map<string,Option*>();
return CommandLineOptions; return *CommandLineOptions;
}
static Option *getOption(const string &Str) {
if (CommandLineOptions == 0) return 0;
map<string,Option*>::iterator I = CommandLineOptions->find(Str);
return I != CommandLineOptions->end() ? I->second : 0;
} }
static vector<Option*> &getPositionalOpts() { static vector<Option*> &getPositionalOpts() {
@ -39,13 +46,26 @@ static vector<Option*> &getPositionalOpts() {
return Positional; return Positional;
} }
static void AddArgument(const string &ArgName, Option *Opt) { static void AddArgument(const char *ArgName, Option *Opt) {
if (getOpts().find(ArgName) != getOpts().end()) { if (getOption(ArgName)) {
cerr << "CommandLine Error: Argument '" << ArgName cerr << "CommandLine Error: Argument '" << ArgName
<< "' defined more than once!\n"; << "' defined more than once!\n";
} else { } else {
// Add argument to the argument map! // Add argument to the argument map!
getOpts().insert(std::make_pair(ArgName, Opt)); getOpts()[ArgName] = Opt;
}
}
// RemoveArgument - It's possible that the argument is no longer in the map if
// options have already been processed and the map has been deleted!
//
static void RemoveArgument(const char *ArgName, Option *Opt) {
if (CommandLineOptions == 0) return;
assert(getOption(ArgName) == Opt && "Arg not in map!");
CommandLineOptions->erase(ArgName);
if (CommandLineOptions->empty()) {
delete CommandLineOptions;
CommandLineOptions = 0;
} }
} }
@ -103,25 +123,25 @@ static inline bool isPrefixedOrGrouping(const Option *O) {
static Option *getOptionPred(std::string Name, unsigned &Length, static Option *getOptionPred(std::string Name, unsigned &Length,
bool (*Pred)(const Option*)) { bool (*Pred)(const Option*)) {
map<string, Option*>::iterator I = getOpts().find(Name); Option *Op = getOption(Name);
if (I != getOpts().end() && Pred(I->second)) { if (Op && Pred(Op)) {
Length = Name.length(); Length = Name.length();
return I->second; return Op;
} }
if (Name.size() == 1) return 0; if (Name.size() == 1) return 0;
do { do {
Name.erase(Name.end()-1, Name.end()); // Chop off the last character... Name.erase(Name.end()-1, Name.end()); // Chop off the last character...
I = getOpts().find(Name); Op = getOption(Name);
// Loop while we haven't found an option and Name still has at least two // Loop while we haven't found an option and Name still has at least two
// characters in it (so that the next iteration will not be the empty // characters in it (so that the next iteration will not be the empty
// string... // string...
} while ((I == getOpts().end() || !Pred(I->second)) && Name.size() > 1); } while ((Op == 0 || !Pred(Op)) && Name.size() > 1);
if (I != getOpts().end() && Pred(I->second)) { if (Op && Pred(Op)) {
Length = Name.length(); Length = Name.length();
return I->second; // Found one! return Op; // Found one!
} }
return 0; // No option found! return 0; // No option found!
} }
@ -384,7 +404,8 @@ void cl::ParseCommandLineOptions(int &argc, char **argv,
// Free all of the memory allocated to the map. Command line options may only // Free all of the memory allocated to the map. Command line options may only
// be processed once! // be processed once!
Opts.clear(); delete CommandLineOptions;
CommandLineOptions = 0;
PositionalOpts.clear(); PositionalOpts.clear();
// If we had an error processing our arguments, don't let the program execute // If we had an error processing our arguments, don't let the program execute
@ -445,8 +466,7 @@ void Option::addArgument(const char *ArgStr) {
void Option::removeArgument(const char *ArgStr) { void Option::removeArgument(const char *ArgStr) {
if (ArgStr[0]) { if (ArgStr[0]) {
assert(getOpts()[ArgStr] == this && "Arg not in map!"); RemoveArgument(ArgStr, this);
getOpts().erase(ArgStr);
} else if (getFormattingFlag() == Positional) { } else if (getFormattingFlag() == Positional) {
vector<Option*>::iterator I = vector<Option*>::iterator I =
std::find(getPositionalOpts().begin(), getPositionalOpts().end(), this); std::find(getPositionalOpts().begin(), getPositionalOpts().end(), this);