Home | History | Annotate | Line # | Download | only in Option
      1 //===- OptTable.cpp - Option Table Implementation -------------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "llvm/Option/OptTable.h"
     10 #include "llvm/ADT/STLExtras.h"
     11 #include "llvm/ADT/StringRef.h"
     12 #include "llvm/ADT/StringSet.h"
     13 #include "llvm/Option/Arg.h"
     14 #include "llvm/Option/ArgList.h"
     15 #include "llvm/Option/OptSpecifier.h"
     16 #include "llvm/Option/Option.h"
     17 #include "llvm/Support/CommandLine.h" // for expandResponseFiles
     18 #include "llvm/Support/Compiler.h"
     19 #include "llvm/Support/ErrorHandling.h"
     20 #include "llvm/Support/raw_ostream.h"
     21 #include <algorithm>
     22 #include <cassert>
     23 #include <cctype>
     24 #include <cstring>
     25 #include <map>
     26 #include <string>
     27 #include <utility>
     28 #include <vector>
     29 
     30 using namespace llvm;
     31 using namespace llvm::opt;
     32 
     33 namespace llvm {
     34 namespace opt {
     35 
     36 // Ordering on Info. The ordering is *almost* case-insensitive lexicographic,
     37 // with an exception. '\0' comes at the end of the alphabet instead of the
     38 // beginning (thus options precede any other options which prefix them).
     39 static int StrCmpOptionNameIgnoreCase(const char *A, const char *B) {
     40   const char *X = A, *Y = B;
     41   char a = tolower(*A), b = tolower(*B);
     42   while (a == b) {
     43     if (a == '\0')
     44       return 0;
     45 
     46     a = tolower(*++X);
     47     b = tolower(*++Y);
     48   }
     49 
     50   if (a == '\0') // A is a prefix of B.
     51     return 1;
     52   if (b == '\0') // B is a prefix of A.
     53     return -1;
     54 
     55   // Otherwise lexicographic.
     56   return (a < b) ? -1 : 1;
     57 }
     58 
     59 #ifndef NDEBUG
     60 static int StrCmpOptionName(const char *A, const char *B) {
     61   if (int N = StrCmpOptionNameIgnoreCase(A, B))
     62     return N;
     63   return strcmp(A, B);
     64 }
     65 
     66 static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
     67   if (&A == &B)
     68     return false;
     69 
     70   if (int N = StrCmpOptionName(A.Name, B.Name))
     71     return N < 0;
     72 
     73   for (const char * const *APre = A.Prefixes,
     74                   * const *BPre = B.Prefixes;
     75                           *APre != nullptr && *BPre != nullptr; ++APre, ++BPre){
     76     if (int N = StrCmpOptionName(*APre, *BPre))
     77       return N < 0;
     78   }
     79 
     80   // Names are the same, check that classes are in order; exactly one
     81   // should be joined, and it should succeed the other.
     82   assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) &&
     83          "Unexpected classes for options with same name.");
     84   return B.Kind == Option::JoinedClass;
     85 }
     86 #endif
     87 
     88 // Support lower_bound between info and an option name.
     89 static inline bool operator<(const OptTable::Info &I, const char *Name) {
     90   return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0;
     91 }
     92 
     93 } // end namespace opt
     94 } // end namespace llvm
     95 
     96 OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
     97 
     98 OptTable::OptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase)
     99     : OptionInfos(OptionInfos), IgnoreCase(IgnoreCase) {
    100   // Explicitly zero initialize the error to work around a bug in array
    101   // value-initialization on MinGW with gcc 4.3.5.
    102 
    103   // Find start of normal options.
    104   for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
    105     unsigned Kind = getInfo(i + 1).Kind;
    106     if (Kind == Option::InputClass) {
    107       assert(!TheInputOptionID && "Cannot have multiple input options!");
    108       TheInputOptionID = getInfo(i + 1).ID;
    109     } else if (Kind == Option::UnknownClass) {
    110       assert(!TheUnknownOptionID && "Cannot have multiple unknown options!");
    111       TheUnknownOptionID = getInfo(i + 1).ID;
    112     } else if (Kind != Option::GroupClass) {
    113       FirstSearchableIndex = i;
    114       break;
    115     }
    116   }
    117   assert(FirstSearchableIndex != 0 && "No searchable options?");
    118 
    119 #ifndef NDEBUG
    120   // Check that everything after the first searchable option is a
    121   // regular option class.
    122   for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
    123     Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
    124     assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
    125             Kind != Option::GroupClass) &&
    126            "Special options should be defined first!");
    127   }
    128 
    129   // Check that options are in order.
    130   for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions(); i != e; ++i){
    131     if (!(getInfo(i) < getInfo(i + 1))) {
    132       getOption(i).dump();
    133       getOption(i + 1).dump();
    134       llvm_unreachable("Options are not in order!");
    135     }
    136   }
    137 #endif
    138 
    139   // Build prefixes.
    140   for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions() + 1;
    141                 i != e; ++i) {
    142     if (const char *const *P = getInfo(i).Prefixes) {
    143       for (; *P != nullptr; ++P) {
    144         PrefixesUnion.insert(*P);
    145       }
    146     }
    147   }
    148 
    149   // Build prefix chars.
    150   for (StringSet<>::const_iterator I = PrefixesUnion.begin(),
    151                                    E = PrefixesUnion.end(); I != E; ++I) {
    152     StringRef Prefix = I->getKey();
    153     for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end();
    154                                    C != CE; ++C)
    155       if (!is_contained(PrefixChars, *C))
    156         PrefixChars.push_back(*C);
    157   }
    158 }
    159 
    160 OptTable::~OptTable() = default;
    161 
    162 const Option OptTable::getOption(OptSpecifier Opt) const {
    163   unsigned id = Opt.getID();
    164   if (id == 0)
    165     return Option(nullptr, nullptr);
    166   assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
    167   return Option(&getInfo(id), this);
    168 }
    169 
    170 static bool isInput(const StringSet<> &Prefixes, StringRef Arg) {
    171   if (Arg == "-")
    172     return true;
    173   for (StringSet<>::const_iterator I = Prefixes.begin(),
    174                                    E = Prefixes.end(); I != E; ++I)
    175     if (Arg.startswith(I->getKey()))
    176       return false;
    177   return true;
    178 }
    179 
    180 /// \returns Matched size. 0 means no match.
    181 static unsigned matchOption(const OptTable::Info *I, StringRef Str,
    182                             bool IgnoreCase) {
    183   for (const char * const *Pre = I->Prefixes; *Pre != nullptr; ++Pre) {
    184     StringRef Prefix(*Pre);
    185     if (Str.startswith(Prefix)) {
    186       StringRef Rest = Str.substr(Prefix.size());
    187       bool Matched = IgnoreCase
    188           ? Rest.startswith_lower(I->Name)
    189           : Rest.startswith(I->Name);
    190       if (Matched)
    191         return Prefix.size() + StringRef(I->Name).size();
    192     }
    193   }
    194   return 0;
    195 }
    196 
    197 // Returns true if one of the Prefixes + In.Names matches Option
    198 static bool optionMatches(const OptTable::Info &In, StringRef Option) {
    199   if (In.Prefixes) {
    200     StringRef InName(In.Name);
    201     for (size_t I = 0; In.Prefixes[I]; I++)
    202       if (Option.endswith(InName))
    203         if (Option.slice(0, Option.size() - InName.size()) == In.Prefixes[I])
    204           return true;
    205   }
    206   return false;
    207 }
    208 
    209 // This function is for flag value completion.
    210 // Eg. When "-stdlib=" and "l" was passed to this function, it will return
    211 // appropiriate values for stdlib, which starts with l.
    212 std::vector<std::string>
    213 OptTable::suggestValueCompletions(StringRef Option, StringRef Arg) const {
    214   // Search all options and return possible values.
    215   for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
    216     const Info &In = OptionInfos[I];
    217     if (!In.Values || !optionMatches(In, Option))
    218       continue;
    219 
    220     SmallVector<StringRef, 8> Candidates;
    221     StringRef(In.Values).split(Candidates, ",", -1, false);
    222 
    223     std::vector<std::string> Result;
    224     for (StringRef Val : Candidates)
    225       if (Val.startswith(Arg) && Arg.compare(Val))
    226         Result.push_back(std::string(Val));
    227     return Result;
    228   }
    229   return {};
    230 }
    231 
    232 std::vector<std::string>
    233 OptTable::findByPrefix(StringRef Cur, unsigned int DisableFlags) const {
    234   std::vector<std::string> Ret;
    235   for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
    236     const Info &In = OptionInfos[I];
    237     if (!In.Prefixes || (!In.HelpText && !In.GroupID))
    238       continue;
    239     if (In.Flags & DisableFlags)
    240       continue;
    241 
    242     for (int I = 0; In.Prefixes[I]; I++) {
    243       std::string S = std::string(In.Prefixes[I]) + std::string(In.Name) + "\t";
    244       if (In.HelpText)
    245         S += In.HelpText;
    246       if (StringRef(S).startswith(Cur) && S != std::string(Cur) + "\t")
    247         Ret.push_back(S);
    248     }
    249   }
    250   return Ret;
    251 }
    252 
    253 unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
    254                                unsigned FlagsToInclude, unsigned FlagsToExclude,
    255                                unsigned MinimumLength) const {
    256   assert(!Option.empty());
    257 
    258   // Consider each [option prefix + option name] pair as a candidate, finding
    259   // the closest match.
    260   unsigned BestDistance = UINT_MAX;
    261   for (const Info &CandidateInfo :
    262        ArrayRef<Info>(OptionInfos).drop_front(FirstSearchableIndex)) {
    263     StringRef CandidateName = CandidateInfo.Name;
    264 
    265     // We can eliminate some option prefix/name pairs as candidates right away:
    266     // * Ignore option candidates with empty names, such as "--", or names
    267     //   that do not meet the minimum length.
    268     if (CandidateName.empty() || CandidateName.size() < MinimumLength)
    269       continue;
    270 
    271     // * If FlagsToInclude were specified, ignore options that don't include
    272     //   those flags.
    273     if (FlagsToInclude && !(CandidateInfo.Flags & FlagsToInclude))
    274       continue;
    275     // * Ignore options that contain the FlagsToExclude.
    276     if (CandidateInfo.Flags & FlagsToExclude)
    277       continue;
    278 
    279     // * Ignore positional argument option candidates (which do not
    280     //   have prefixes).
    281     if (!CandidateInfo.Prefixes)
    282       continue;
    283 
    284     // Now check if the candidate ends with a character commonly used when
    285     // delimiting an option from its value, such as '=' or ':'. If it does,
    286     // attempt to split the given option based on that delimiter.
    287     StringRef LHS, RHS;
    288     char Last = CandidateName.back();
    289     bool CandidateHasDelimiter = Last == '=' || Last == ':';
    290     std::string NormalizedName = std::string(Option);
    291     if (CandidateHasDelimiter) {
    292       std::tie(LHS, RHS) = Option.split(Last);
    293       NormalizedName = std::string(LHS);
    294       if (Option.find(Last) == LHS.size())
    295         NormalizedName += Last;
    296     }
    297 
    298     // Consider each possible prefix for each candidate to find the most
    299     // appropriate one. For example, if a user asks for "--helm", suggest
    300     // "--help" over "-help".
    301     for (int P = 0;
    302          const char *const CandidatePrefix = CandidateInfo.Prefixes[P]; P++) {
    303       std::string Candidate = (CandidatePrefix + CandidateName).str();
    304       StringRef CandidateRef = Candidate;
    305       unsigned Distance =
    306           CandidateRef.edit_distance(NormalizedName, /*AllowReplacements=*/true,
    307                                      /*MaxEditDistance=*/BestDistance);
    308       if (RHS.empty() && CandidateHasDelimiter) {
    309         // The Candidate ends with a = or : delimiter, but the option passed in
    310         // didn't contain the delimiter (or doesn't have anything after it).
    311         // In that case, penalize the correction: `-nodefaultlibs` is more
    312         // likely to be a spello for `-nodefaultlib` than `-nodefaultlib:` even
    313         // though both have an unmodified editing distance of 1, since the
    314         // latter would need an argument.
    315         ++Distance;
    316       }
    317       if (Distance < BestDistance) {
    318         BestDistance = Distance;
    319         NearestString = (Candidate + RHS).str();
    320       }
    321     }
    322   }
    323   return BestDistance;
    324 }
    325 
    326 bool OptTable::addValues(const char *Option, const char *Values) {
    327   for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
    328     Info &In = OptionInfos[I];
    329     if (optionMatches(In, Option)) {
    330       In.Values = Values;
    331       return true;
    332     }
    333   }
    334   return false;
    335 }
    336 
    337 // Parse a single argument, return the new argument, and update Index. If
    338 // GroupedShortOptions is true, -a matches "-abc" and the argument in Args will
    339 // be updated to "-bc". This overload does not support
    340 // FlagsToInclude/FlagsToExclude or case insensitive options.
    341 Arg *OptTable::parseOneArgGrouped(InputArgList &Args, unsigned &Index) const {
    342   // Anything that doesn't start with PrefixesUnion is an input, as is '-'
    343   // itself.
    344   const char *CStr = Args.getArgString(Index);
    345   StringRef Str(CStr);
    346   if (isInput(PrefixesUnion, Str))
    347     return new Arg(getOption(TheInputOptionID), Str, Index++, CStr);
    348 
    349   const Info *End = OptionInfos.data() + OptionInfos.size();
    350   StringRef Name = Str.ltrim(PrefixChars);
    351   const Info *Start = std::lower_bound(
    352       OptionInfos.data() + FirstSearchableIndex, End, Name.data());
    353   const Info *Fallback = nullptr;
    354   unsigned Prev = Index;
    355 
    356   // Search for the option which matches Str.
    357   for (; Start != End; ++Start) {
    358     unsigned ArgSize = matchOption(Start, Str, IgnoreCase);
    359     if (!ArgSize)
    360       continue;
    361 
    362     Option Opt(Start, this);
    363     if (Arg *A = Opt.accept(Args, StringRef(Args.getArgString(Index), ArgSize),
    364                             false, Index))
    365       return A;
    366 
    367     // If Opt is a Flag of length 2 (e.g. "-a"), we know it is a prefix of
    368     // the current argument (e.g. "-abc"). Match it as a fallback if no longer
    369     // option (e.g. "-ab") exists.
    370     if (ArgSize == 2 && Opt.getKind() == Option::FlagClass)
    371       Fallback = Start;
    372 
    373     // Otherwise, see if the argument is missing.
    374     if (Prev != Index)
    375       return nullptr;
    376   }
    377   if (Fallback) {
    378     Option Opt(Fallback, this);
    379     if (Arg *A = Opt.accept(Args, Str.substr(0, 2), true, Index)) {
    380       if (Str.size() == 2)
    381         ++Index;
    382       else
    383         Args.replaceArgString(Index, Twine('-') + Str.substr(2));
    384       return A;
    385     }
    386   }
    387 
    388   return new Arg(getOption(TheUnknownOptionID), Str, Index++, CStr);
    389 }
    390 
    391 Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
    392                            unsigned FlagsToInclude,
    393                            unsigned FlagsToExclude) const {
    394   unsigned Prev = Index;
    395   const char *Str = Args.getArgString(Index);
    396 
    397   // Anything that doesn't start with PrefixesUnion is an input, as is '-'
    398   // itself.
    399   if (isInput(PrefixesUnion, Str))
    400     return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
    401 
    402   const Info *Start = OptionInfos.data() + FirstSearchableIndex;
    403   const Info *End = OptionInfos.data() + OptionInfos.size();
    404   StringRef Name = StringRef(Str).ltrim(PrefixChars);
    405 
    406   // Search for the first next option which could be a prefix.
    407   Start = std::lower_bound(Start, End, Name.data());
    408 
    409   // Options are stored in sorted order, with '\0' at the end of the
    410   // alphabet. Since the only options which can accept a string must
    411   // prefix it, we iteratively search for the next option which could
    412   // be a prefix.
    413   //
    414   // FIXME: This is searching much more than necessary, but I am
    415   // blanking on the simplest way to make it fast. We can solve this
    416   // problem when we move to TableGen.
    417   for (; Start != End; ++Start) {
    418     unsigned ArgSize = 0;
    419     // Scan for first option which is a proper prefix.
    420     for (; Start != End; ++Start)
    421       if ((ArgSize = matchOption(Start, Str, IgnoreCase)))
    422         break;
    423     if (Start == End)
    424       break;
    425 
    426     Option Opt(Start, this);
    427 
    428     if (FlagsToInclude && !Opt.hasFlag(FlagsToInclude))
    429       continue;
    430     if (Opt.hasFlag(FlagsToExclude))
    431       continue;
    432 
    433     // See if this option matches.
    434     if (Arg *A = Opt.accept(Args, StringRef(Args.getArgString(Index), ArgSize),
    435                             false, Index))
    436       return A;
    437 
    438     // Otherwise, see if this argument was missing values.
    439     if (Prev != Index)
    440       return nullptr;
    441   }
    442 
    443   // If we failed to find an option and this arg started with /, then it's
    444   // probably an input path.
    445   if (Str[0] == '/')
    446     return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
    447 
    448   return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str);
    449 }
    450 
    451 InputArgList OptTable::ParseArgs(ArrayRef<const char *> ArgArr,
    452                                  unsigned &MissingArgIndex,
    453                                  unsigned &MissingArgCount,
    454                                  unsigned FlagsToInclude,
    455                                  unsigned FlagsToExclude) const {
    456   InputArgList Args(ArgArr.begin(), ArgArr.end());
    457 
    458   // FIXME: Handle '@' args (or at least error on them).
    459 
    460   MissingArgIndex = MissingArgCount = 0;
    461   unsigned Index = 0, End = ArgArr.size();
    462   while (Index < End) {
    463     // Ingore nullptrs, they are response file's EOL markers
    464     if (Args.getArgString(Index) == nullptr) {
    465       ++Index;
    466       continue;
    467     }
    468     // Ignore empty arguments (other things may still take them as arguments).
    469     StringRef Str = Args.getArgString(Index);
    470     if (Str == "") {
    471       ++Index;
    472       continue;
    473     }
    474 
    475     unsigned Prev = Index;
    476     Arg *A = GroupedShortOptions
    477                  ? parseOneArgGrouped(Args, Index)
    478                  : ParseOneArg(Args, Index, FlagsToInclude, FlagsToExclude);
    479     assert((Index > Prev || GroupedShortOptions) &&
    480            "Parser failed to consume argument.");
    481 
    482     // Check for missing argument error.
    483     if (!A) {
    484       assert(Index >= End && "Unexpected parser error.");
    485       assert(Index - Prev - 1 && "No missing arguments!");
    486       MissingArgIndex = Prev;
    487       MissingArgCount = Index - Prev - 1;
    488       break;
    489     }
    490 
    491     Args.append(A);
    492   }
    493 
    494   return Args;
    495 }
    496 
    497 InputArgList OptTable::parseArgs(int Argc, char *const *Argv,
    498                                  OptSpecifier Unknown, StringSaver &Saver,
    499                                  function_ref<void(StringRef)> ErrorFn) const {
    500   SmallVector<const char *, 0> NewArgv;
    501   // The environment variable specifies initial options which can be overridden
    502   // by commnad line options.
    503   cl::expandResponseFiles(Argc, Argv, EnvVar, Saver, NewArgv);
    504 
    505   unsigned MAI, MAC;
    506   opt::InputArgList Args = ParseArgs(makeArrayRef(NewArgv), MAI, MAC);
    507   if (MAC)
    508     ErrorFn((Twine(Args.getArgString(MAI)) + ": missing argument").str());
    509 
    510   // For each unknwon option, call ErrorFn with a formatted error message. The
    511   // message includes a suggested alternative option spelling if available.
    512   std::string Nearest;
    513   for (const opt::Arg *A : Args.filtered(Unknown)) {
    514     std::string Spelling = A->getAsString(Args);
    515     if (findNearest(Spelling, Nearest) > 1)
    516       ErrorFn("unknown argument '" + A->getAsString(Args) + "'");
    517     else
    518       ErrorFn("unknown argument '" + A->getAsString(Args) +
    519               "', did you mean '" + Nearest + "'?");
    520   }
    521   return Args;
    522 }
    523 
    524 static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
    525   const Option O = Opts.getOption(Id);
    526   std::string Name = O.getPrefixedName();
    527 
    528   // Add metavar, if used.
    529   switch (O.getKind()) {
    530   case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
    531     llvm_unreachable("Invalid option with help text.");
    532 
    533   case Option::MultiArgClass:
    534     if (const char *MetaVarName = Opts.getOptionMetaVar(Id)) {
    535       // For MultiArgs, metavar is full list of all argument names.
    536       Name += ' ';
    537       Name += MetaVarName;
    538     }
    539     else {
    540       // For MultiArgs<N>, if metavar not supplied, print <value> N times.
    541       for (unsigned i=0, e=O.getNumArgs(); i< e; ++i) {
    542         Name += " <value>";
    543       }
    544     }
    545     break;
    546 
    547   case Option::FlagClass:
    548     break;
    549 
    550   case Option::ValuesClass:
    551     break;
    552 
    553   case Option::SeparateClass: case Option::JoinedOrSeparateClass:
    554   case Option::RemainingArgsClass: case Option::RemainingArgsJoinedClass:
    555     Name += ' ';
    556     LLVM_FALLTHROUGH;
    557   case Option::JoinedClass: case Option::CommaJoinedClass:
    558   case Option::JoinedAndSeparateClass:
    559     if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
    560       Name += MetaVarName;
    561     else
    562       Name += "<value>";
    563     break;
    564   }
    565 
    566   return Name;
    567 }
    568 
    569 namespace {
    570 struct OptionInfo {
    571   std::string Name;
    572   StringRef HelpText;
    573 };
    574 } // namespace
    575 
    576 static void PrintHelpOptionList(raw_ostream &OS, StringRef Title,
    577                                 std::vector<OptionInfo> &OptionHelp) {
    578   OS << Title << ":\n";
    579 
    580   // Find the maximum option length.
    581   unsigned OptionFieldWidth = 0;
    582   for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
    583     // Limit the amount of padding we are willing to give up for alignment.
    584     unsigned Length = OptionHelp[i].Name.size();
    585     if (Length <= 23)
    586       OptionFieldWidth = std::max(OptionFieldWidth, Length);
    587   }
    588 
    589   const unsigned InitialPad = 2;
    590   for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
    591     const std::string &Option = OptionHelp[i].Name;
    592     int Pad = OptionFieldWidth - int(Option.size());
    593     OS.indent(InitialPad) << Option;
    594 
    595     // Break on long option names.
    596     if (Pad < 0) {
    597       OS << "\n";
    598       Pad = OptionFieldWidth + InitialPad;
    599     }
    600     OS.indent(Pad + 1) << OptionHelp[i].HelpText << '\n';
    601   }
    602 }
    603 
    604 static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
    605   unsigned GroupID = Opts.getOptionGroupID(Id);
    606 
    607   // If not in a group, return the default help group.
    608   if (!GroupID)
    609     return "OPTIONS";
    610 
    611   // Abuse the help text of the option groups to store the "help group"
    612   // name.
    613   //
    614   // FIXME: Split out option groups.
    615   if (const char *GroupHelp = Opts.getOptionHelpText(GroupID))
    616     return GroupHelp;
    617 
    618   // Otherwise keep looking.
    619   return getOptionHelpGroup(Opts, GroupID);
    620 }
    621 
    622 void OptTable::PrintHelp(raw_ostream &OS, const char *Usage, const char *Title,
    623                          bool ShowHidden, bool ShowAllAliases) const {
    624   PrintHelp(OS, Usage, Title, /*Include*/ 0, /*Exclude*/
    625             (ShowHidden ? 0 : HelpHidden), ShowAllAliases);
    626 }
    627 
    628 void OptTable::PrintHelp(raw_ostream &OS, const char *Usage, const char *Title,
    629                          unsigned FlagsToInclude, unsigned FlagsToExclude,
    630                          bool ShowAllAliases) const {
    631   OS << "OVERVIEW: " << Title << "\n\n";
    632   OS << "USAGE: " << Usage << "\n\n";
    633 
    634   // Render help text into a map of group-name to a list of (option, help)
    635   // pairs.
    636   std::map<std::string, std::vector<OptionInfo>> GroupedOptionHelp;
    637 
    638   for (unsigned Id = 1, e = getNumOptions() + 1; Id != e; ++Id) {
    639     // FIXME: Split out option groups.
    640     if (getOptionKind(Id) == Option::GroupClass)
    641       continue;
    642 
    643     unsigned Flags = getInfo(Id).Flags;
    644     if (FlagsToInclude && !(Flags & FlagsToInclude))
    645       continue;
    646     if (Flags & FlagsToExclude)
    647       continue;
    648 
    649     // If an alias doesn't have a help text, show a help text for the aliased
    650     // option instead.
    651     const char *HelpText = getOptionHelpText(Id);
    652     if (!HelpText && ShowAllAliases) {
    653       const Option Alias = getOption(Id).getAlias();
    654       if (Alias.isValid())
    655         HelpText = getOptionHelpText(Alias.getID());
    656     }
    657 
    658     if (HelpText) {
    659       const char *HelpGroup = getOptionHelpGroup(*this, Id);
    660       const std::string &OptName = getOptionHelpName(*this, Id);
    661       GroupedOptionHelp[HelpGroup].push_back({OptName, HelpText});
    662     }
    663   }
    664 
    665   for (auto& OptionGroup : GroupedOptionHelp) {
    666     if (OptionGroup.first != GroupedOptionHelp.begin()->first)
    667       OS << "\n";
    668     PrintHelpOptionList(OS, OptionGroup.first, OptionGroup.second);
    669   }
    670 
    671   OS.flush();
    672 }
    673