From e8e258b1a7e54a77c802e8b309d0a60a62d1a00d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 29 Jul 2002 20:58:42 +0000 Subject: [PATCH] * 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 --- lib/Support/CommandLine.cpp | 50 ++++++++++++++++++++--------- support/lib/Support/CommandLine.cpp | 50 ++++++++++++++++++++--------- 2 files changed, 70 insertions(+), 30 deletions(-) diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index fc3d62b3570..c00c42bcb99 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -29,9 +29,16 @@ using std::cerr; // 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 map *CommandLineOptions = 0; static map &getOpts() { - static map CommandLineOptions; - return CommandLineOptions; + if (CommandLineOptions == 0) CommandLineOptions = new map(); + return *CommandLineOptions; +} + +static Option *getOption(const string &Str) { + if (CommandLineOptions == 0) return 0; + map::iterator I = CommandLineOptions->find(Str); + return I != CommandLineOptions->end() ? I->second : 0; } static vector &getPositionalOpts() { @@ -39,13 +46,26 @@ static vector &getPositionalOpts() { return Positional; } -static void AddArgument(const string &ArgName, Option *Opt) { - if (getOpts().find(ArgName) != getOpts().end()) { +static void AddArgument(const char *ArgName, Option *Opt) { + if (getOption(ArgName)) { cerr << "CommandLine Error: Argument '" << ArgName << "' defined more than once!\n"; } else { // 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, bool (*Pred)(const Option*)) { - map::iterator I = getOpts().find(Name); - if (I != getOpts().end() && Pred(I->second)) { + Option *Op = getOption(Name); + if (Op && Pred(Op)) { Length = Name.length(); - return I->second; + return Op; } if (Name.size() == 1) return 0; do { 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 // characters in it (so that the next iteration will not be the empty // 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(); - return I->second; // Found one! + return Op; // Found one! } 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 // be processed once! - Opts.clear(); + delete CommandLineOptions; + CommandLineOptions = 0; PositionalOpts.clear(); // 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) { if (ArgStr[0]) { - assert(getOpts()[ArgStr] == this && "Arg not in map!"); - getOpts().erase(ArgStr); + RemoveArgument(ArgStr, this); } else if (getFormattingFlag() == Positional) { vector::iterator I = std::find(getPositionalOpts().begin(), getPositionalOpts().end(), this); diff --git a/support/lib/Support/CommandLine.cpp b/support/lib/Support/CommandLine.cpp index fc3d62b3570..c00c42bcb99 100644 --- a/support/lib/Support/CommandLine.cpp +++ b/support/lib/Support/CommandLine.cpp @@ -29,9 +29,16 @@ using std::cerr; // 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 map *CommandLineOptions = 0; static map &getOpts() { - static map CommandLineOptions; - return CommandLineOptions; + if (CommandLineOptions == 0) CommandLineOptions = new map(); + return *CommandLineOptions; +} + +static Option *getOption(const string &Str) { + if (CommandLineOptions == 0) return 0; + map::iterator I = CommandLineOptions->find(Str); + return I != CommandLineOptions->end() ? I->second : 0; } static vector &getPositionalOpts() { @@ -39,13 +46,26 @@ static vector &getPositionalOpts() { return Positional; } -static void AddArgument(const string &ArgName, Option *Opt) { - if (getOpts().find(ArgName) != getOpts().end()) { +static void AddArgument(const char *ArgName, Option *Opt) { + if (getOption(ArgName)) { cerr << "CommandLine Error: Argument '" << ArgName << "' defined more than once!\n"; } else { // 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, bool (*Pred)(const Option*)) { - map::iterator I = getOpts().find(Name); - if (I != getOpts().end() && Pred(I->second)) { + Option *Op = getOption(Name); + if (Op && Pred(Op)) { Length = Name.length(); - return I->second; + return Op; } if (Name.size() == 1) return 0; do { 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 // characters in it (so that the next iteration will not be the empty // 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(); - return I->second; // Found one! + return Op; // Found one! } 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 // be processed once! - Opts.clear(); + delete CommandLineOptions; + CommandLineOptions = 0; PositionalOpts.clear(); // 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) { if (ArgStr[0]) { - assert(getOpts()[ArgStr] == this && "Arg not in map!"); - getOpts().erase(ArgStr); + RemoveArgument(ArgStr, this); } else if (getFormattingFlag() == Positional) { vector::iterator I = std::find(getPositionalOpts().begin(), getPositionalOpts().end(), this);