diff options
| -rw-r--r-- | llvm/include/llvm/Support/CommandLine.h | 6 | ||||
| -rw-r--r-- | llvm/lib/Support/CommandLine.cpp | 34 | ||||
| -rw-r--r-- | llvm/unittests/Support/CommandLineTest.cpp | 19 | 
3 files changed, 49 insertions, 10 deletions
diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h index ffd1d30ca3a..799b41fbf8b 100644 --- a/llvm/include/llvm/Support/CommandLine.h +++ b/llvm/include/llvm/Support/CommandLine.h @@ -30,6 +30,7 @@  #include "llvm/ADT/iterator_range.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h"  #include <cassert>  #include <climits>  #include <cstddef> @@ -362,7 +363,10 @@ public:                               bool MultiArg = false);    // Prints option name followed by message.  Always returns true. -  bool error(const Twine &Message, StringRef ArgName = StringRef()); +  bool error(const Twine &Message, StringRef ArgName = StringRef(), raw_ostream &Errs = llvm::errs()); +  bool error(const Twine &Message, raw_ostream &Errs) { +    return error(Message, StringRef(), Errs); +  }    inline int getNumOccurrences() const { return NumOccurrences; }    inline void reset() { NumOccurrences = 0; } diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp index f1be43c027b..a1e659a01c8 100644 --- a/llvm/lib/Support/CommandLine.cpp +++ b/llvm/lib/Support/CommandLine.cpp @@ -1270,8 +1270,15 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,      // If this is a named positional argument, just remember that it is the      // active one... -    if (Handler->getFormattingFlag() == cl::Positional) +    if (Handler->getFormattingFlag() == cl::Positional) { +      if ((Handler->getMiscFlags() & PositionalEatsArgs) && !Value.empty()) { +        Handler->error("This argument does not take a value.\n" +                       "\tInstead, it consumes any positional arguments until " +                       "the next recognized option.", *Errs); +        ErrorParsing = true; +      }        ActivePositionalArg = Handler; +    }      else        ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i);    } @@ -1396,15 +1403,15 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,  // Option Base class implementation  // -bool Option::error(const Twine &Message, StringRef ArgName) { +bool Option::error(const Twine &Message, StringRef ArgName, raw_ostream &Errs) {    if (!ArgName.data())      ArgName = ArgStr;    if (ArgName.empty()) -    errs() << HelpStr; // Be nice for positional arguments +    Errs << HelpStr; // Be nice for positional arguments    else -    errs() << GlobalParser->ProgramName << ": for the -" << ArgName; +    Errs << GlobalParser->ProgramName << ": for the -" << ArgName; -  errs() << " option: " << Message << "\n"; +  Errs << " option: " << Message << "\n";    return true;  } @@ -1474,8 +1481,12 @@ void alias::printOptionInfo(size_t GlobalWidth) const {  size_t basic_parser_impl::getOptionWidth(const Option &O) const {    size_t Len = O.ArgStr.size();    auto ValName = getValueName(); -  if (!ValName.empty()) -    Len += getValueStr(O, ValName).size() + 3; +  if (!ValName.empty()) { +    size_t FormattingLen = 3; +    if (O.getMiscFlags() & PositionalEatsArgs) +      FormattingLen = 6; +    Len += getValueStr(O, ValName).size() + FormattingLen; +  }    return Len + 6;  } @@ -1488,8 +1499,13 @@ void basic_parser_impl::printOptionInfo(const Option &O,    outs() << "  -" << O.ArgStr;    auto ValName = getValueName(); -  if (!ValName.empty()) -    outs() << "=<" << getValueStr(O, ValName) << '>'; +  if (!ValName.empty()) { +    if (O.getMiscFlags() & PositionalEatsArgs) { +      outs() << " <" << getValueStr(O, ValName) << ">..."; +    } else { +      outs() << "=<" << getValueStr(O, ValName) << '>'; +    } +  }    Option::printHelpStr(O.HelpStr, GlobalWidth, getOptionWidth(O));  } diff --git a/llvm/unittests/Support/CommandLineTest.cpp b/llvm/unittests/Support/CommandLineTest.cpp index 8657504e507..a52420f2bb4 100644 --- a/llvm/unittests/Support/CommandLineTest.cpp +++ b/llvm/unittests/Support/CommandLineTest.cpp @@ -816,4 +816,23 @@ TEST(CommandLineTest, ReadConfigFile) {    llvm::sys::fs::remove(TestDir);  } +TEST(CommandLineTest, PositionalEatArgsError) { +  static cl::list<std::string> PosEatArgs("positional-eat-args", cl::Positional, +    cl::desc("<arguments>..."), cl::ZeroOrMore, +    cl::PositionalEatsArgs); + +  const char *args[] = {"prog", "-positional-eat-args=XXXX"}; +  const char *args2[] = {"prog", "-positional-eat-args=XXXX", "-foo"}; +  const char *args3[] = {"prog", "-positional-eat-args", "-foo"}; + +  std::string Errs; +  raw_string_ostream OS(Errs); +  EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS)); OS.flush(); +  EXPECT_FALSE(Errs.empty()); Errs.clear(); +  EXPECT_FALSE(cl::ParseCommandLineOptions(3, args2, StringRef(), &OS)); OS.flush(); +  EXPECT_FALSE(Errs.empty()); Errs.clear(); +  EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), &OS)); OS.flush(); +  EXPECT_TRUE(Errs.empty()); +} +  }  // anonymous namespace  | 

