Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Option/OptTable.cpp
Line
Count
Source (jump to first uncovered line)
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/ADT/STLExtras.h"
10
#include "llvm/ADT/StringRef.h"
11
#include "llvm/ADT/StringSet.h"
12
#include "llvm/Option/Arg.h"
13
#include "llvm/Option/ArgList.h"
14
#include "llvm/Option/Option.h"
15
#include "llvm/Option/OptSpecifier.h"
16
#include "llvm/Option/OptTable.h"
17
#include "llvm/Support/Compiler.h"
18
#include "llvm/Support/ErrorHandling.h"
19
#include "llvm/Support/raw_ostream.h"
20
#include <algorithm>
21
#include <cassert>
22
#include <cctype>
23
#include <cstring>
24
#include <map>
25
#include <string>
26
#include <utility>
27
#include <vector>
28
29
using namespace llvm;
30
using namespace llvm::opt;
31
32
namespace llvm {
33
namespace opt {
34
35
// Ordering on Info. The ordering is *almost* case-insensitive lexicographic,
36
// with an exception. '\0' comes at the end of the alphabet instead of the
37
// beginning (thus options precede any other options which prefix them).
38
33.9M
static int StrCmpOptionNameIgnoreCase(const char *A, const char *B) {
39
33.9M
  const char *X = A, *Y = B;
40
33.9M
  char a = tolower(*A), b = tolower(*B);
41
92.2M
  while (a == b) {
42
60.8M
    if (a == '\0')
43
2.62M
      return 0;
44
58.2M
45
58.2M
    a = tolower(*++X);
46
58.2M
    b = tolower(*++Y);
47
58.2M
  }
48
33.9M
49
33.9M
  
if (31.3M
a == '\0'31.3M
) // A is a prefix of B.
50
651k
    return 1;
51
30.7M
  if (b == '\0') // B is a prefix of A.
52
2.25M
    return -1;
53
28.4M
54
28.4M
  // Otherwise lexicographic.
55
28.4M
  return (a < b) ? 
-112.7M
:
115.6M
;
56
28.4M
}
57
58
#ifndef NDEBUG
59
static int StrCmpOptionName(const char *A, const char *B) {
60
  if (int N = StrCmpOptionNameIgnoreCase(A, B))
61
    return N;
62
  return strcmp(A, B);
63
}
64
65
static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
66
  if (&A == &B)
67
    return false;
68
69
  if (int N = StrCmpOptionName(A.Name, B.Name))
70
    return N < 0;
71
72
  for (const char * const *APre = A.Prefixes,
73
                  * const *BPre = B.Prefixes;
74
                          *APre != nullptr && *BPre != nullptr; ++APre, ++BPre){
75
    if (int N = StrCmpOptionName(*APre, *BPre))
76
      return N < 0;
77
  }
78
79
  // Names are the same, check that classes are in order; exactly one
80
  // should be joined, and it should succeed the other.
81
  assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) &&
82
         "Unexpected classes for options with same name.");
83
  return B.Kind == Option::JoinedClass;
84
}
85
#endif
86
87
// Support lower_bound between info and an option name.
88
33.9M
static inline bool operator<(const OptTable::Info &I, const char *Name) {
89
33.9M
  return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0;
90
33.9M
}
91
92
} // end namespace opt
93
} // end namespace llvm
94
95
12.7k
OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
96
97
OptTable::OptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase)
98
111k
    : OptionInfos(OptionInfos), IgnoreCase(IgnoreCase) {
99
111k
  // Explicitly zero initialize the error to work around a bug in array
100
111k
  // value-initialization on MinGW with gcc 4.3.5.
101
111k
102
111k
  // Find start of normal options.
103
6.14M
  for (unsigned i = 0, e = getNumOptions(); i != e; 
++i6.03M
) {
104
6.14M
    unsigned Kind = getInfo(i + 1).Kind;
105
6.14M
    if (Kind == Option::InputClass) {
106
111k
      assert(!TheInputOptionID && "Cannot have multiple input options!");
107
111k
      TheInputOptionID = getInfo(i + 1).ID;
108
6.03M
    } else if (Kind == Option::UnknownClass) {
109
111k
      assert(!TheUnknownOptionID && "Cannot have multiple unknown options!");
110
111k
      TheUnknownOptionID = getInfo(i + 1).ID;
111
5.92M
    } else if (Kind != Option::GroupClass) {
112
111k
      FirstSearchableIndex = i;
113
111k
      break;
114
111k
    }
115
6.14M
  }
116
111k
  assert(FirstSearchableIndex != 0 && "No searchable options?");
117
111k
118
#ifndef NDEBUG
119
  // Check that everything after the first searchable option is a
120
  // regular option class.
121
  for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
122
    Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
123
    assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
124
            Kind != Option::GroupClass) &&
125
           "Special options should be defined first!");
126
  }
127
128
  // Check that options are in order.
129
  for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions(); i != e; ++i){
130
    if (!(getInfo(i) < getInfo(i + 1))) {
131
      getOption(i).dump();
132
      getOption(i + 1).dump();
133
      llvm_unreachable("Options are not in order!");
134
    }
135
  }
136
#endif
137
138
111k
  // Build prefixes.
139
111k
  for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions() + 1;
140
261M
                i != e; 
++i261M
) {
141
261M
    if (const char *const *P = getInfo(i).Prefixes) {
142
552M
      for (; *P != nullptr; 
++P291M
) {
143
291M
        PrefixesUnion.insert(*P);
144
291M
      }
145
261M
    }
146
261M
  }
147
111k
148
111k
  // Build prefix chars.
149
111k
  for (StringSet<>::const_iterator I = PrefixesUnion.begin(),
150
444k
                                   E = PrefixesUnion.end(); I != E; 
++I332k
) {
151
332k
    StringRef Prefix = I->getKey();
152
332k
    for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end();
153
782k
                                   C != CE; 
++C449k
)
154
449k
      if (!is_contained(PrefixChars, *C))
155
218k
        PrefixChars.push_back(*C);
156
332k
  }
157
111k
}
158
159
111k
OptTable::~OptTable() = default;
160
161
226M
const Option OptTable::getOption(OptSpecifier Opt) const {
162
226M
  unsigned id = Opt.getID();
163
226M
  if (id == 0)
164
157M
    return Option(nullptr, nullptr);
165
68.8M
  assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
166
68.8M
  return Option(&getInfo(id), this);
167
68.8M
}
168
169
2.99M
static bool isInput(const StringSet<> &Prefixes, StringRef Arg) {
170
2.99M
  if (Arg == "-")
171
134
    return true;
172
2.99M
  for (StringSet<>::const_iterator I = Prefixes.begin(),
173
6.17M
                                   E = Prefixes.end(); I != E; 
++I3.17M
)
174
6.12M
    if (Arg.startswith(I->getKey()))
175
2.94M
      return false;
176
2.99M
  
return true50.1k
;
177
2.99M
}
178
179
/// \returns Matched size. 0 means no match.
180
static unsigned matchOption(const OptTable::Info *I, StringRef Str,
181
30.8M
                            bool IgnoreCase) {
182
64.5M
  for (const char * const *Pre = I->Prefixes; *Pre != nullptr; 
++Pre33.7M
) {
183
36.7M
    StringRef Prefix(*Pre);
184
36.7M
    if (Str.startswith(Prefix)) {
185
24.2M
      StringRef Rest = Str.substr(Prefix.size());
186
24.2M
      bool Matched = IgnoreCase
187
24.2M
          ? 
Rest.startswith_lower(I->Name)23.8k
188
24.2M
          : 
Rest.startswith(I->Name)24.2M
;
189
24.2M
      if (Matched)
190
3.00M
        return Prefix.size() + StringRef(I->Name).size();
191
24.2M
    }
192
36.7M
  }
193
30.8M
  
return 027.8M
;
194
30.8M
}
195
196
// Returns true if one of the Prefixes + In.Names matches Option
197
480M
static bool optionMatches(const OptTable::Info &In, StringRef Option) {
198
480M
  if (In.Prefixes)
199
1.00G
    
for (size_t I = 0; 480M
In.Prefixes[I];
I++519M
)
200
520M
      if (Option == std::string(In.Prefixes[I]) + In.Name)
201
317k
        return true;
202
480M
  
return false480M
;
203
480M
}
204
205
// This function is for flag value completion.
206
// Eg. When "-stdlib=" and "l" was passed to this function, it will return
207
// appropiriate values for stdlib, which starts with l.
208
std::vector<std::string>
209
41
OptTable::suggestValueCompletions(StringRef Option, StringRef Arg) const {
210
41
  // Search all options and return possible values.
211
76.7k
  for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; 
I++76.6k
) {
212
76.6k
    const Info &In = OptionInfos[I];
213
76.6k
    if (!In.Values || 
!optionMatches(In, Option)1.00k
)
214
76.6k
      continue;
215
20
216
20
    SmallVector<StringRef, 8> Candidates;
217
20
    StringRef(In.Values).split(Candidates, ",", -1, false);
218
20
219
20
    std::vector<std::string> Result;
220
20
    for (StringRef Val : Candidates)
221
361
      if (Val.startswith(Arg) && 
Arg.compare(Val)325
)
222
325
        Result.push_back(Val);
223
20
    return Result;
224
20
  }
225
41
  
return {}21
;
226
41
}
227
228
std::vector<std::string>
229
12
OptTable::findByPrefix(StringRef Cur, unsigned short DisableFlags) const {
230
12
  std::vector<std::string> Ret;
231
29.5k
  for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; 
I++29.5k
) {
232
29.5k
    const Info &In = OptionInfos[I];
233
29.5k
    if (!In.Prefixes || (!In.HelpText && 
!In.GroupID16.2k
))
234
3.87k
      continue;
235
25.6k
    if (In.Flags & DisableFlags)
236
5.38k
      continue;
237
20.2k
238
43.6k
    
for (int I = 0; 20.2k
In.Prefixes[I];
I++23.3k
) {
239
23.3k
      std::string S = std::string(In.Prefixes[I]) + std::string(In.Name) + "\t";
240
23.3k
      if (In.HelpText)
241
12.1k
        S += In.HelpText;
242
23.3k
      if (StringRef(S).startswith(Cur) && 
S.compare(std::string(Cur) + "\t")1.67k
)
243
1.67k
        Ret.push_back(S);
244
23.3k
    }
245
20.2k
  }
246
12
  return Ret;
247
12
}
248
249
unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
250
                               unsigned FlagsToInclude, unsigned FlagsToExclude,
251
209
                               unsigned MinimumLength) const {
252
209
  assert(!Option.empty());
253
209
254
209
  // Consider each [option prefix + option name] pair as a candidate, finding
255
209
  // the closest match.
256
209
  unsigned BestDistance = UINT_MAX;
257
209
  for (const Info &CandidateInfo :
258
278k
       ArrayRef<Info>(OptionInfos).drop_front(FirstSearchableIndex)) {
259
278k
    StringRef CandidateName = CandidateInfo.Name;
260
278k
261
278k
    // We can eliminate some option prefix/name pairs as candidates right away:
262
278k
    // * Ignore option candidates with empty names, such as "--", or names
263
278k
    //   that do not meet the minimum length.
264
278k
    if (CandidateName.empty() || 
CandidateName.size() < MinimumLength278k
)
265
25.6k
      continue;
266
253k
267
253k
    // * If FlagsToInclude were specified, ignore options that don't include
268
253k
    //   those flags.
269
253k
    if (FlagsToInclude && 
!(CandidateInfo.Flags & FlagsToInclude)100k
)
270
79.8k
      continue;
271
173k
    // * Ignore options that contain the FlagsToExclude.
272
173k
    if (CandidateInfo.Flags & FlagsToExclude)
273
27.3k
      continue;
274
146k
275
146k
    // * Ignore positional argument option candidates (which do not
276
146k
    //   have prefixes).
277
146k
    if (!CandidateInfo.Prefixes)
278
0
      continue;
279
146k
280
146k
    // Now check if the candidate ends with a character commonly used when
281
146k
    // delimiting an option from its value, such as '=' or ':'. If it does,
282
146k
    // attempt to split the given option based on that delimiter.
283
146k
    StringRef LHS, RHS;
284
146k
    char Last = CandidateName.back();
285
146k
    bool CandidateHasDelimiter = Last == '=' || 
Last == ':'127k
;
286
146k
    std::string NormalizedName = Option;
287
146k
    if (CandidateHasDelimiter) {
288
24.2k
      std::tie(LHS, RHS) = Option.split(Last);
289
24.2k
      NormalizedName = LHS;
290
24.2k
      if (Option.find(Last) == LHS.size())
291
1.25k
        NormalizedName += Last;
292
24.2k
    }
293
146k
294
146k
    // Consider each possible prefix for each candidate to find the most
295
146k
    // appropriate one. For example, if a user asks for "--helm", suggest
296
146k
    // "--help" over "-help".
297
146k
    for (int P = 0;
298
328k
         const char *const CandidatePrefix = CandidateInfo.Prefixes[P]; 
P++182k
) {
299
182k
      std::string Candidate = (CandidatePrefix + CandidateName).str();
300
182k
      StringRef CandidateRef = Candidate;
301
182k
      unsigned Distance =
302
182k
          CandidateRef.edit_distance(NormalizedName, /*AllowReplacements=*/true,
303
182k
                                     /*MaxEditDistance=*/BestDistance);
304
182k
      if (RHS.empty() && 
CandidateHasDelimiter181k
) {
305
39.0k
        // The Candidate ends with a = or : delimiter, but the option passed in
306
39.0k
        // didn't contain the delimiter (or doesn't have anything after it).
307
39.0k
        // In that case, penalize the correction: `-nodefaultlibs` is more
308
39.0k
        // likely to be a spello for `-nodefaultlib` than `-nodefaultlib:` even
309
39.0k
        // though both have an unmodified editing distance of 1, since the
310
39.0k
        // latter would need an argument.
311
39.0k
        ++Distance;
312
39.0k
      }
313
182k
      if (Distance < BestDistance) {
314
979
        BestDistance = Distance;
315
979
        NearestString = (Candidate + RHS).str();
316
979
      }
317
182k
    }
318
146k
  }
319
209
  return BestDistance;
320
209
}
321
322
317k
bool OptTable::addValues(const char *Option, const char *Values) {
323
480M
  for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; 
I++480M
) {
324
480M
    Info &In = OptionInfos[I];
325
480M
    if (optionMatches(In, Option)) {
326
317k
      In.Values = Values;
327
317k
      return true;
328
317k
    }
329
480M
  }
330
317k
  
return false0
;
331
317k
}
332
333
Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
334
                           unsigned FlagsToInclude,
335
2.99M
                           unsigned FlagsToExclude) const {
336
2.99M
  unsigned Prev = Index;
337
2.99M
  const char *Str = Args.getArgString(Index);
338
2.99M
339
2.99M
  // Anything that doesn't start with PrefixesUnion is an input, as is '-'
340
2.99M
  // itself.
341
2.99M
  if (isInput(PrefixesUnion, Str))
342
50.2k
    return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
343
2.94M
344
2.94M
  const Info *Start = OptionInfos.data() + FirstSearchableIndex;
345
2.94M
  const Info *End = OptionInfos.data() + OptionInfos.size();
346
2.94M
  StringRef Name = StringRef(Str).ltrim(PrefixChars);
347
2.94M
348
2.94M
  // Search for the first next option which could be a prefix.
349
2.94M
  Start = std::lower_bound(Start, End, Name.data());
350
2.94M
351
2.94M
  // Options are stored in sorted order, with '\0' at the end of the
352
2.94M
  // alphabet. Since the only options which can accept a string must
353
2.94M
  // prefix it, we iteratively search for the next option which could
354
2.94M
  // be a prefix.
355
2.94M
  //
356
2.94M
  // FIXME: This is searching much more than necessary, but I am
357
2.94M
  // blanking on the simplest way to make it fast. We can solve this
358
2.94M
  // problem when we move to TableGen.
359
3.06M
  for (; Start != End; 
++Start124k
) {
360
3.06M
    unsigned ArgSize = 0;
361
3.06M
    // Scan for first option which is a proper prefix.
362
30.9M
    for (; Start != End; 
++Start27.8M
)
363
30.8M
      if ((ArgSize = matchOption(Start, Str, IgnoreCase)))
364
3.00M
        break;
365
3.06M
    if (Start == End)
366
62.2k
      break;
367
3.00M
368
3.00M
    Option Opt(Start, this);
369
3.00M
370
3.00M
    if (FlagsToInclude && 
!Opt.hasFlag(FlagsToInclude)1.67M
)
371
38.5k
      continue;
372
2.96M
    if (Opt.hasFlag(FlagsToExclude))
373
20.9k
      continue;
374
2.94M
375
2.94M
    // See if this option matches.
376
2.94M
    if (Arg *A = Opt.accept(Args, Index, ArgSize))
377
2.87M
      return A;
378
65.3k
379
65.3k
    // Otherwise, see if this argument was missing values.
380
65.3k
    if (Prev != Index)
381
14
      return nullptr;
382
65.3k
  }
383
2.94M
384
2.94M
  // If we failed to find an option and this arg started with /, then it's
385
2.94M
  // probably an input path.
386
2.94M
  
if (62.2k
Str[0] == '/'62.2k
)
387
62.1k
    return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
388
140
389
140
  return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str);
390
140
}
391
392
InputArgList OptTable::ParseArgs(ArrayRef<const char *> ArgArr,
393
                                 unsigned &MissingArgIndex,
394
                                 unsigned &MissingArgCount,
395
                                 unsigned FlagsToInclude,
396
114k
                                 unsigned FlagsToExclude) const {
397
114k
  InputArgList Args(ArgArr.begin(), ArgArr.end());
398
114k
399
114k
  // FIXME: Handle '@' args (or at least error on them).
400
114k
401
114k
  MissingArgIndex = MissingArgCount = 0;
402
114k
  unsigned Index = 0, End = ArgArr.size();
403
3.10M
  while (Index < End) {
404
2.99M
    // Ingore nullptrs, they are response file's EOL markers
405
2.99M
    if (Args.getArgString(Index) == nullptr) {
406
713
      ++Index;
407
713
      continue;
408
713
    }
409
2.99M
    // Ignore empty arguments (other things may still take them as arguments).
410
2.99M
    StringRef Str = Args.getArgString(Index);
411
2.99M
    if (Str == "") {
412
34
      ++Index;
413
34
      continue;
414
34
    }
415
2.99M
416
2.99M
    unsigned Prev = Index;
417
2.99M
    Arg *A = ParseOneArg(Args, Index, FlagsToInclude, FlagsToExclude);
418
2.99M
    assert(Index > Prev && "Parser failed to consume argument.");
419
2.99M
420
2.99M
    // Check for missing argument error.
421
2.99M
    if (!A) {
422
11
      assert(Index >= End && "Unexpected parser error.");
423
11
      assert(Index - Prev - 1 && "No missing arguments!");
424
11
      MissingArgIndex = Prev;
425
11
      MissingArgCount = Index - Prev - 1;
426
11
      break;
427
11
    }
428
2.99M
429
2.99M
    Args.append(A);
430
2.99M
  }
431
114k
432
114k
  return Args;
433
114k
}
434
435
4.58k
static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
436
4.58k
  const Option O = Opts.getOption(Id);
437
4.58k
  std::string Name = O.getPrefixedName();
438
4.58k
439
4.58k
  // Add metavar, if used.
440
4.58k
  switch (O.getKind()) {
441
4.58k
  
case Option::GroupClass: 0
case Option::InputClass: 0
case Option::UnknownClass:
442
0
    llvm_unreachable("Invalid option with help text.");
443
0
444
2
  case Option::MultiArgClass:
445
2
    if (const char *MetaVarName = Opts.getOptionMetaVar(Id)) {
446
2
      // For MultiArgs, metavar is full list of all argument names.
447
2
      Name += ' ';
448
2
      Name += MetaVarName;
449
2
    }
450
0
    else {
451
0
      // For MultiArgs<N>, if metavar not supplied, print <value> N times.
452
0
      for (unsigned i=0, e=O.getNumArgs(); i< e; ++i) {
453
0
        Name += " <value>";
454
0
      }
455
0
    }
456
2
    break;
457
0
458
3.07k
  case Option::FlagClass:
459
3.07k
    break;
460
0
461
0
  case Option::ValuesClass:
462
0
    break;
463
0
464
474
  case Option::SeparateClass: case Option::JoinedOrSeparateClass:
465
474
  case Option::RemainingArgsClass: case Option::RemainingArgsJoinedClass:
466
474
    Name += ' ';
467
474
    LLVM_FALLTHROUGH;
468
1.50k
  case Option::JoinedClass: case Option::CommaJoinedClass:
469
1.50k
  case Option::JoinedAndSeparateClass:
470
1.50k
    if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
471
591
      Name += MetaVarName;
472
918
    else
473
918
      Name += "<value>";
474
1.50k
    break;
475
4.58k
  }
476
4.58k
477
4.58k
  return Name;
478
4.58k
}
479
480
namespace {
481
struct OptionInfo {
482
  std::string Name;
483
  StringRef HelpText;
484
};
485
} // namespace
486
487
static void PrintHelpOptionList(raw_ostream &OS, StringRef Title,
488
43
                                std::vector<OptionInfo> &OptionHelp) {
489
43
  OS << Title << ":\n";
490
43
491
43
  // Find the maximum option length.
492
43
  unsigned OptionFieldWidth = 0;
493
4.62k
  for (unsigned i = 0, e = OptionHelp.size(); i != e; 
++i4.58k
) {
494
4.58k
    // Limit the amount of padding we are willing to give up for alignment.
495
4.58k
    unsigned Length = OptionHelp[i].Name.size();
496
4.58k
    if (Length <= 23)
497
3.33k
      OptionFieldWidth = std::max(OptionFieldWidth, Length);
498
4.58k
  }
499
43
500
43
  const unsigned InitialPad = 2;
501
4.62k
  for (unsigned i = 0, e = OptionHelp.size(); i != e; 
++i4.58k
) {
502
4.58k
    const std::string &Option = OptionHelp[i].Name;
503
4.58k
    int Pad = OptionFieldWidth - int(Option.size());
504
4.58k
    OS.indent(InitialPad) << Option;
505
4.58k
506
4.58k
    // Break on long option names.
507
4.58k
    if (Pad < 0) {
508
1.24k
      OS << "\n";
509
1.24k
      Pad = OptionFieldWidth + InitialPad;
510
1.24k
    }
511
4.58k
    OS.indent(Pad + 1) << OptionHelp[i].HelpText << '\n';
512
4.58k
  }
513
43
}
514
515
9.81k
static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
516
9.81k
  unsigned GroupID = Opts.getOptionGroupID(Id);
517
9.81k
518
9.81k
  // If not in a group, return the default help group.
519
9.81k
  if (!GroupID)
520
4.10k
    return "OPTIONS";
521
5.71k
522
5.71k
  // Abuse the help text of the option groups to store the "help group"
523
5.71k
  // name.
524
5.71k
  //
525
5.71k
  // FIXME: Split out option groups.
526
5.71k
  if (const char *GroupHelp = Opts.getOptionHelpText(GroupID))
527
476
    return GroupHelp;
528
5.23k
529
5.23k
  // Otherwise keep looking.
530
5.23k
  return getOptionHelpGroup(Opts, GroupID);
531
5.23k
}
532
533
void OptTable::PrintHelp(raw_ostream &OS, const char *Usage, const char *Title,
534
24
                         bool ShowHidden, bool ShowAllAliases) const {
535
24
  PrintHelp(OS, Usage, Title, /*Include*/ 0, /*Exclude*/
536
24
            (ShowHidden ? 
00
: HelpHidden), ShowAllAliases);
537
24
}
538
539
void OptTable::PrintHelp(raw_ostream &OS, const char *Usage, const char *Title,
540
                         unsigned FlagsToInclude, unsigned FlagsToExclude,
541
31
                         bool ShowAllAliases) const {
542
31
  OS << "OVERVIEW: " << Title << "\n\n";
543
31
  OS << "USAGE: " << Usage << "\n\n";
544
31
545
31
  // Render help text into a map of group-name to a list of (option, help)
546
31
  // pairs.
547
31
  std::map<std::string, std::vector<OptionInfo>> GroupedOptionHelp;
548
31
549
19.5k
  for (unsigned Id = 1, e = getNumOptions() + 1; Id != e; 
++Id19.5k
) {
550
19.5k
    // FIXME: Split out option groups.
551
19.5k
    if (getOptionKind(Id) == Option::GroupClass)
552
398
      continue;
553
19.1k
554
19.1k
    unsigned Flags = getInfo(Id).Flags;
555
19.1k
    if (FlagsToInclude && 
!(Flags & FlagsToInclude)9.85k
)
556
7.41k
      continue;
557
11.7k
    if (Flags & FlagsToExclude)
558
1.89k
      continue;
559
9.86k
560
9.86k
    // If an alias doesn't have a help text, show a help text for the aliased
561
9.86k
    // option instead.
562
9.86k
    const char *HelpText = getOptionHelpText(Id);
563
9.86k
    if (!HelpText && 
ShowAllAliases5.29k
) {
564
217
      const Option Alias = getOption(Id).getAlias();
565
217
      if (Alias.isValid())
566
14
        HelpText = getOptionHelpText(Alias.getID());
567
217
    }
568
9.86k
569
9.86k
    if (HelpText) {
570
4.58k
      const char *HelpGroup = getOptionHelpGroup(*this, Id);
571
4.58k
      const std::string &OptName = getOptionHelpName(*this, Id);
572
4.58k
      GroupedOptionHelp[HelpGroup].push_back({OptName, HelpText});
573
4.58k
    }
574
9.86k
  }
575
31
576
43
  for (auto& OptionGroup : GroupedOptionHelp) {
577
43
    if (OptionGroup.first != GroupedOptionHelp.begin()->first)
578
12
      OS << "\n";
579
43
    PrintHelpOptionList(OS, OptionGroup.first, OptionGroup.second);
580
43
  }
581
31
582
31
  OS.flush();
583
31
}