summaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm18/include/llvm/Option/OptTable.h
blob: 8147c89882fc48cc71c8ae1bd110f60e366013a7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
#pragma once

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

//===- OptTable.h - Option Table --------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_OPTION_OPTTABLE_H
#define LLVM_OPTION_OPTTABLE_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Option/OptSpecifier.h"
#include "llvm/Support/StringSaver.h"
#include <cassert>
#include <string>
#include <vector>

namespace llvm {

class raw_ostream;
template <typename Fn> class function_ref;

namespace opt {

class Arg;
class ArgList;
class InputArgList;
class Option;

/// Helper for overload resolution while transitioning from
/// FlagsToInclude/FlagsToExclude APIs to VisibilityMask APIs.
class Visibility {
  unsigned Mask = ~0U;

public:
  explicit Visibility(unsigned Mask) : Mask(Mask) {}
  Visibility() = default;

  operator unsigned() const { return Mask; }
};

/// Provide access to the Option info table.
///
/// The OptTable class provides a layer of indirection which allows Option
/// instance to be created lazily. In the common case, only a few options will
/// be needed at runtime; the OptTable class maintains enough information to
/// parse command lines without instantiating Options, while letting other
/// parts of the driver still use Option instances where convenient.
class OptTable {
public:
  /// Entry for a single option instance in the option data table.
  struct Info {
    /// A null terminated array of prefix strings to apply to name while
    /// matching.
    ArrayRef<StringLiteral> Prefixes;
    StringLiteral PrefixedName;
    const char *HelpText;
    const char *MetaVar;
    unsigned ID;
    unsigned char Kind;
    unsigned char Param;
    unsigned int Flags;
    unsigned int Visibility;
    unsigned short GroupID;
    unsigned short AliasID;
    const char *AliasArgs;
    const char *Values;

    StringRef getName() const {
      unsigned PrefixLength = Prefixes.empty() ? 0 : Prefixes[0].size();
      return PrefixedName.drop_front(PrefixLength);
    }
  };

private:
  /// The option information table.
  ArrayRef<Info> OptionInfos;
  bool IgnoreCase;
  bool GroupedShortOptions = false;
  bool DashDashParsing = false;
  const char *EnvVar = nullptr;

  unsigned InputOptionID = 0;
  unsigned UnknownOptionID = 0;

protected:
  /// The index of the first option which can be parsed (i.e., is not a
  /// special option like 'input' or 'unknown', and is not an option group).
  unsigned FirstSearchableIndex = 0;

  /// The union of the first element of all option prefixes.
  SmallString<8> PrefixChars;

  /// The union of all option prefixes. If an argument does not begin with
  /// one of these, it is an input.
  virtual ArrayRef<StringLiteral> getPrefixesUnion() const = 0;

private:
  const Info &getInfo(OptSpecifier Opt) const {
    unsigned id = Opt.getID();
    assert(id > 0 && id - 1 < getNumOptions() && "Invalid Option ID.");
    return OptionInfos[id - 1];
  }

  std::unique_ptr<Arg> parseOneArgGrouped(InputArgList &Args,
                                          unsigned &Index) const;

protected:
  /// Initialize OptTable using Tablegen'ed OptionInfos. Child class must
  /// manually call \c buildPrefixChars once they are fully constructed.
  OptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase = false);

  /// Build (or rebuild) the PrefixChars member.
  void buildPrefixChars();

public:
  virtual ~OptTable();

  /// Return the total number of option classes.
  unsigned getNumOptions() const { return OptionInfos.size(); }

  /// Get the given Opt's Option instance, lazily creating it
  /// if necessary.
  ///
  /// \return The option, or null for the INVALID option id.
  const Option getOption(OptSpecifier Opt) const;

  /// Lookup the name of the given option.
  StringRef getOptionName(OptSpecifier id) const {
    return getInfo(id).getName();
  }

  /// Get the kind of the given option.
  unsigned getOptionKind(OptSpecifier id) const {
    return getInfo(id).Kind;
  }

  /// Get the group id for the given option.
  unsigned getOptionGroupID(OptSpecifier id) const {
    return getInfo(id).GroupID;
  }

  /// Get the help text to use to describe this option.
  const char *getOptionHelpText(OptSpecifier id) const {
    return getInfo(id).HelpText;
  }

  /// Get the meta-variable name to use when describing
  /// this options values in the help text.
  const char *getOptionMetaVar(OptSpecifier id) const {
    return getInfo(id).MetaVar;
  }

  /// Specify the environment variable where initial options should be read.
  void setInitialOptionsFromEnvironment(const char *E) { EnvVar = E; }

  /// Support grouped short options. e.g. -ab represents -a -b.
  void setGroupedShortOptions(bool Value) { GroupedShortOptions = Value; }

  /// Set whether "--" stops option parsing and treats all subsequent arguments
  /// as positional. E.g. -- -a -b gives two positional inputs.
  void setDashDashParsing(bool Value) { DashDashParsing = Value; }

  /// Find possible value for given flags. This is used for shell
  /// autocompletion.
  ///
  /// \param [in] Option - Key flag like "-stdlib=" when "-stdlib=l"
  /// was passed to clang.
  ///
  /// \param [in] Arg - Value which we want to autocomplete like "l"
  /// when "-stdlib=l" was passed to clang.
  ///
  /// \return The vector of possible values.
  std::vector<std::string> suggestValueCompletions(StringRef Option,
                                                   StringRef Arg) const;

  /// Find flags from OptTable which starts with Cur.
  ///
  /// \param [in] Cur - String prefix that all returned flags need
  //  to start with.
  ///
  /// \return The vector of flags which start with Cur.
  std::vector<std::string> findByPrefix(StringRef Cur,
                                        Visibility VisibilityMask,
                                        unsigned int DisableFlags) const;

  /// Find the OptTable option that most closely matches the given string.
  ///
  /// \param [in] Option - A string, such as "-stdlibs=l", that represents user
  /// input of an option that may not exist in the OptTable. Note that the
  /// string includes prefix dashes "-" as well as values "=l".
  /// \param [out] NearestString - The nearest option string found in the
  /// OptTable.
  /// \param [in] VisibilityMask - Only include options with any of these
  ///                              visibility flags set.
  /// \param [in] MinimumLength - Don't find options shorter than this length.
  /// For example, a minimum length of 3 prevents "-x" from being considered
  /// near to "-S".
  /// \param [in] MaximumDistance - Don't find options whose distance is greater
  /// than this value.
  ///
  /// \return The edit distance of the nearest string found.
  unsigned findNearest(StringRef Option, std::string &NearestString,
                       Visibility VisibilityMask = Visibility(),
                       unsigned MinimumLength = 4,
                       unsigned MaximumDistance = UINT_MAX) const;

  unsigned findNearest(StringRef Option, std::string &NearestString,
                       unsigned FlagsToInclude, unsigned FlagsToExclude = 0,
                       unsigned MinimumLength = 4,
                       unsigned MaximumDistance = UINT_MAX) const;

private:
  unsigned
  internalFindNearest(StringRef Option, std::string &NearestString,
                      unsigned MinimumLength, unsigned MaximumDistance,
                      std::function<bool(const Info &)> ExcludeOption) const;

public:
  bool findExact(StringRef Option, std::string &ExactString,
                 Visibility VisibilityMask = Visibility()) const {
    return findNearest(Option, ExactString, VisibilityMask, 4, 0) == 0;
  }

  bool findExact(StringRef Option, std::string &ExactString,
                 unsigned FlagsToInclude, unsigned FlagsToExclude = 0) const {
    return findNearest(Option, ExactString, FlagsToInclude, FlagsToExclude, 4,
                       0) == 0;
  }

  /// Parse a single argument; returning the new argument and
  /// updating Index.
  ///
  /// \param [in,out] Index - The current parsing position in the argument
  /// string list; on return this will be the index of the next argument
  /// string to parse.
  /// \param [in] VisibilityMask - Only include options with any of these
  /// visibility flags set.
  ///
  /// \return The parsed argument, or 0 if the argument is missing values
  /// (in which case Index still points at the conceptual next argument string
  /// to parse).
  std::unique_ptr<Arg>
  ParseOneArg(const ArgList &Args, unsigned &Index,
              Visibility VisibilityMask = Visibility()) const;

  std::unique_ptr<Arg> ParseOneArg(const ArgList &Args, unsigned &Index,
                                   unsigned FlagsToInclude,
                                   unsigned FlagsToExclude) const;

private:
  std::unique_ptr<Arg>
  internalParseOneArg(const ArgList &Args, unsigned &Index,
                      std::function<bool(const Option &)> ExcludeOption) const;

public:
  /// Parse an list of arguments into an InputArgList.
  ///
  /// The resulting InputArgList will reference the strings in [\p ArgBegin,
  /// \p ArgEnd), and their lifetime should extend past that of the returned
  /// InputArgList.
  ///
  /// The only error that can occur in this routine is if an argument is
  /// missing values; in this case \p MissingArgCount will be non-zero.
  ///
  /// \param MissingArgIndex - On error, the index of the option which could
  /// not be parsed.
  /// \param MissingArgCount - On error, the number of missing options.
  /// \param VisibilityMask - Only include options with any of these
  /// visibility flags set.
  /// \return An InputArgList; on error this will contain all the options
  /// which could be parsed.
  InputArgList ParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex,
                         unsigned &MissingArgCount,
                         Visibility VisibilityMask = Visibility()) const;

  InputArgList ParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex,
                         unsigned &MissingArgCount, unsigned FlagsToInclude,
                         unsigned FlagsToExclude = 0) const;

private:
  InputArgList
  internalParseArgs(ArrayRef<const char *> Args, unsigned &MissingArgIndex,
                    unsigned &MissingArgCount,
                    std::function<bool(const Option &)> ExcludeOption) const;

public:
  /// A convenience helper which handles optional initial options populated from
  /// an environment variable, expands response files recursively and parses
  /// options.
  ///
  /// \param ErrorFn - Called on a formatted error message for missing arguments
  /// or unknown options.
  /// \return An InputArgList; on error this will contain all the options which
  /// could be parsed.
  InputArgList parseArgs(int Argc, char *const *Argv, OptSpecifier Unknown,
                         StringSaver &Saver,
                         std::function<void(StringRef)> ErrorFn) const;

  /// Render the help text for an option table.
  ///
  /// \param OS - The stream to write the help text to.
  /// \param Usage - USAGE: Usage
  /// \param Title - OVERVIEW: Title
  /// \param VisibilityMask - Only in                 Visibility VisibilityMask,clude options with any of these
  ///                         visibility flags set.
  /// \param ShowHidden     - If true, display options marked as HelpHidden
  /// \param ShowAllAliases - If true, display all options including aliases
  ///                         that don't have help texts. By default, we display
  ///                         only options that are not hidden and have help
  ///                         texts.
  void printHelp(raw_ostream &OS, const char *Usage, const char *Title,
                 bool ShowHidden = false, bool ShowAllAliases = false,
                 Visibility VisibilityMask = Visibility()) const;

  void printHelp(raw_ostream &OS, const char *Usage, const char *Title,
                 unsigned FlagsToInclude, unsigned FlagsToExclude,
                 bool ShowAllAliases) const;

private:
  void internalPrintHelp(raw_ostream &OS, const char *Usage, const char *Title,
                         bool ShowHidden, bool ShowAllAliases,
                         std::function<bool(const Info &)> ExcludeOption) const;
};

/// Specialization of OptTable
class GenericOptTable : public OptTable {
  SmallVector<StringLiteral> PrefixesUnionBuffer;

protected:
  GenericOptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase = false);
  ArrayRef<StringLiteral> getPrefixesUnion() const final {
    return PrefixesUnionBuffer;
  }
};

class PrecomputedOptTable : public OptTable {
  ArrayRef<StringLiteral> PrefixesUnion;

protected:
  PrecomputedOptTable(ArrayRef<Info> OptionInfos,
                      ArrayRef<StringLiteral> PrefixesTable,
                      bool IgnoreCase = false)
      : OptTable(OptionInfos, IgnoreCase), PrefixesUnion(PrefixesTable) {
    buildPrefixChars();
  }
  ArrayRef<StringLiteral> getPrefixesUnion() const final {
    return PrefixesUnion;
  }
};

} // end namespace opt

} // end namespace llvm

#define LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(                                       \
    ID_PREFIX, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS,       \
    FLAGS, VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)                       \
  ID_PREFIX##ID

#define LLVM_MAKE_OPT_ID(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS,        \
                         ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT,        \
                         METAVAR, VALUES)                                      \
  LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OPT_, PREFIX, PREFIXED_NAME, ID, KIND,       \
                                  GROUP, ALIAS, ALIASARGS, FLAGS, VISIBILITY,  \
                                  PARAM, HELPTEXT, METAVAR, VALUE)

#define LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(                                \
    ID_PREFIX, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS,       \
    FLAGS, VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)                       \
  llvm::opt::OptTable::Info {                                                  \
    PREFIX, PREFIXED_NAME, HELPTEXT, METAVAR, ID_PREFIX##ID,                   \
        llvm::opt::Option::KIND##Class, PARAM, FLAGS, VISIBILITY,              \
        ID_PREFIX##GROUP, ID_PREFIX##ALIAS, ALIASARGS, VALUES                  \
  }

#define LLVM_CONSTRUCT_OPT_INFO(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, \
                                ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, \
                                METAVAR, VALUES)                               \
  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(                                      \
      OPT_, PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,   \
      VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES)

#endif // LLVM_OPTION_OPTTABLE_H

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif