Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- ArgList.h - Argument List Management ---------------------*- C++ -*-===//
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
#ifndef LLVM_OPTION_ARGLIST_H
10
#define LLVM_OPTION_ARGLIST_H
11
 
12
#include "llvm/ADT/ArrayRef.h"
13
#include "llvm/ADT/DenseMap.h"
14
#include "llvm/ADT/iterator_range.h"
15
#include "llvm/ADT/SmallString.h"
16
#include "llvm/ADT/SmallVector.h"
17
#include "llvm/ADT/StringRef.h"
18
#include "llvm/ADT/Twine.h"
19
#include "llvm/Option/Arg.h"
20
#include "llvm/Option/OptSpecifier.h"
21
#include "llvm/Option/Option.h"
22
#include <algorithm>
23
#include <cstddef>
24
#include <initializer_list>
25
#include <iterator>
26
#include <list>
27
#include <memory>
28
#include <string>
29
#include <utility>
30
#include <vector>
31
 
32
namespace llvm {
33
 
34
class raw_ostream;
35
 
36
namespace opt {
37
 
38
/// arg_iterator - Iterates through arguments stored inside an ArgList.
39
template<typename BaseIter, unsigned NumOptSpecifiers = 0>
40
class arg_iterator {
41
  /// The current argument and the end of the sequence we're iterating.
42
  BaseIter Current, End;
43
 
44
  /// Optional filters on the arguments which will be match. To avoid a
45
  /// zero-sized array, we store one specifier even if we're asked for none.
46
  OptSpecifier Ids[NumOptSpecifiers ? NumOptSpecifiers : 1];
47
 
48
  void SkipToNextArg() {
49
    for (; Current != End; ++Current) {
50
      // Skip erased elements.
51
      if (!*Current)
52
        continue;
53
 
54
      // Done if there are no filters.
55
      if (!NumOptSpecifiers)
56
        return;
57
 
58
      // Otherwise require a match.
59
      const Option &O = (*Current)->getOption();
60
      for (auto Id : Ids) {
61
        if (!Id.isValid())
62
          break;
63
        if (O.matches(Id))
64
          return;
65
      }
66
    }
67
  }
68
 
69
  using Traits = std::iterator_traits<BaseIter>;
70
 
71
public:
72
  using value_type = typename Traits::value_type;
73
  using reference = typename Traits::reference;
74
  using pointer = typename Traits::pointer;
75
  using iterator_category = std::forward_iterator_tag;
76
  using difference_type = std::ptrdiff_t;
77
 
78
  arg_iterator(
79
      BaseIter Current, BaseIter End,
80
      const OptSpecifier (&Ids)[NumOptSpecifiers ? NumOptSpecifiers : 1] = {})
81
      : Current(Current), End(End) {
82
    for (unsigned I = 0; I != NumOptSpecifiers; ++I)
83
      this->Ids[I] = Ids[I];
84
    SkipToNextArg();
85
  }
86
 
87
  reference operator*() const { return *Current; }
88
  pointer operator->() const { return Current; }
89
 
90
  arg_iterator &operator++() {
91
    ++Current;
92
    SkipToNextArg();
93
    return *this;
94
  }
95
 
96
  arg_iterator operator++(int) {
97
    arg_iterator tmp(*this);
98
    ++(*this);
99
    return tmp;
100
  }
101
 
102
  friend bool operator==(arg_iterator LHS, arg_iterator RHS) {
103
    return LHS.Current == RHS.Current;
104
  }
105
  friend bool operator!=(arg_iterator LHS, arg_iterator RHS) {
106
    return !(LHS == RHS);
107
  }
108
};
109
 
110
/// ArgList - Ordered collection of driver arguments.
111
///
112
/// The ArgList class manages a list of Arg instances as well as
113
/// auxiliary data and convenience methods to allow Tools to quickly
114
/// check for the presence of Arg instances for a particular Option
115
/// and to iterate over groups of arguments.
116
class ArgList {
117
public:
118
  using arglist_type = SmallVector<Arg *, 16>;
119
  using iterator = arg_iterator<arglist_type::iterator>;
120
  using const_iterator = arg_iterator<arglist_type::const_iterator>;
121
  using reverse_iterator = arg_iterator<arglist_type::reverse_iterator>;
122
  using const_reverse_iterator =
123
      arg_iterator<arglist_type::const_reverse_iterator>;
124
 
125
  template<unsigned N> using filtered_iterator =
126
      arg_iterator<arglist_type::const_iterator, N>;
127
  template<unsigned N> using filtered_reverse_iterator =
128
      arg_iterator<arglist_type::const_reverse_iterator, N>;
129
 
130
private:
131
  /// The internal list of arguments.
132
  arglist_type Args;
133
 
134
  using OptRange = std::pair<unsigned, unsigned>;
135
  static OptRange emptyRange() { return {-1u, 0u}; }
136
 
137
  /// The first and last index of each different OptSpecifier ID.
138
  DenseMap<unsigned, OptRange> OptRanges;
139
 
140
  /// Get the range of indexes in which options with the specified IDs might
141
  /// reside, or (0, 0) if there are no such options.
142
  OptRange getRange(std::initializer_list<OptSpecifier> Ids) const;
143
 
144
protected:
145
  // Make the default special members protected so they won't be used to slice
146
  // derived objects, but can still be used by derived objects to implement
147
  // their own special members.
148
  ArgList() = default;
149
 
150
  // Explicit move operations to ensure the container is cleared post-move
151
  // otherwise it could lead to a double-delete in the case of moving of an
152
  // InputArgList which deletes the contents of the container. If we could fix
153
  // up the ownership here (delegate storage/ownership to the derived class so
154
  // it can be a container of unique_ptr) this would be simpler.
155
  ArgList(ArgList &&RHS)
156
      : Args(std::move(RHS.Args)), OptRanges(std::move(RHS.OptRanges)) {
157
    RHS.Args.clear();
158
    RHS.OptRanges.clear();
159
  }
160
 
161
  ArgList &operator=(ArgList &&RHS) {
162
    Args = std::move(RHS.Args);
163
    RHS.Args.clear();
164
    OptRanges = std::move(RHS.OptRanges);
165
    RHS.OptRanges.clear();
166
    return *this;
167
  }
168
 
169
  // Protect the dtor to ensure this type is never destroyed polymorphically.
170
  ~ArgList() = default;
171
 
172
  // Implicitly convert a value to an OptSpecifier. Used to work around a bug
173
  // in MSVC's implementation of narrowing conversion checking.
174
  static OptSpecifier toOptSpecifier(OptSpecifier S) { return S; }
175
 
176
public:
177
  /// @name Arg Access
178
  /// @{
179
 
180
  /// append - Append \p A to the arg list.
181
  void append(Arg *A);
182
 
183
  const arglist_type &getArgs() const { return Args; }
184
 
185
  unsigned size() const { return Args.size(); }
186
 
187
  /// @}
188
  /// @name Arg Iteration
189
  /// @{
190
 
191
  iterator begin() { return {Args.begin(), Args.end()}; }
192
  iterator end() { return {Args.end(), Args.end()}; }
193
 
194
  reverse_iterator rbegin() { return {Args.rbegin(), Args.rend()}; }
195
  reverse_iterator rend() { return {Args.rend(), Args.rend()}; }
196
 
197
  const_iterator begin() const { return {Args.begin(), Args.end()}; }
198
  const_iterator end() const { return {Args.end(), Args.end()}; }
199
 
200
  const_reverse_iterator rbegin() const { return {Args.rbegin(), Args.rend()}; }
201
  const_reverse_iterator rend() const { return {Args.rend(), Args.rend()}; }
202
 
203
  template<typename ...OptSpecifiers>
204
  iterator_range<filtered_iterator<sizeof...(OptSpecifiers)>>
205
  filtered(OptSpecifiers ...Ids) const {
206
    OptRange Range = getRange({toOptSpecifier(Ids)...});
207
    auto B = Args.begin() + Range.first;
208
    auto E = Args.begin() + Range.second;
209
    using Iterator = filtered_iterator<sizeof...(OptSpecifiers)>;
210
    return make_range(Iterator(B, E, {toOptSpecifier(Ids)...}),
211
                      Iterator(E, E, {toOptSpecifier(Ids)...}));
212
  }
213
 
214
  template<typename ...OptSpecifiers>
215
  iterator_range<filtered_reverse_iterator<sizeof...(OptSpecifiers)>>
216
  filtered_reverse(OptSpecifiers ...Ids) const {
217
    OptRange Range = getRange({toOptSpecifier(Ids)...});
218
    auto B = Args.rend() - Range.second;
219
    auto E = Args.rend() - Range.first;
220
    using Iterator = filtered_reverse_iterator<sizeof...(OptSpecifiers)>;
221
    return make_range(Iterator(B, E, {toOptSpecifier(Ids)...}),
222
                      Iterator(E, E, {toOptSpecifier(Ids)...}));
223
  }
224
 
225
  /// @}
226
  /// @name Arg Removal
227
  /// @{
228
 
229
  /// eraseArg - Remove any option matching \p Id.
230
  void eraseArg(OptSpecifier Id);
231
 
232
  /// @}
233
  /// @name Arg Access
234
  /// @{
235
 
236
  /// hasArg - Does the arg list contain any option matching \p Id.
237
  ///
238
  /// \p Claim Whether the argument should be claimed, if it exists.
239
  template<typename ...OptSpecifiers>
240
  bool hasArgNoClaim(OptSpecifiers ...Ids) const {
241
    return getLastArgNoClaim(Ids...) != nullptr;
242
  }
243
  template<typename ...OptSpecifiers>
244
  bool hasArg(OptSpecifiers ...Ids) const {
245
    return getLastArg(Ids...) != nullptr;
246
  }
247
 
248
  /// Return true if the arg list contains multiple arguments matching \p Id.
249
  bool hasMultipleArgs(OptSpecifier Id) const {
250
    auto Args = filtered(Id);
251
    return (Args.begin() != Args.end()) && (++Args.begin()) != Args.end();
252
  }
253
 
254
  /// Return the last argument matching \p Id, or null.
255
  template<typename ...OptSpecifiers>
256
  Arg *getLastArg(OptSpecifiers ...Ids) const {
257
    Arg *Res = nullptr;
258
    for (Arg *A : filtered(Ids...)) {
259
      Res = A;
260
      Res->claim();
261
    }
262
    return Res;
263
  }
264
 
265
  /// Return the last argument matching \p Id, or null. Do not "claim" the
266
  /// option (don't mark it as having been used).
267
  template<typename ...OptSpecifiers>
268
  Arg *getLastArgNoClaim(OptSpecifiers ...Ids) const {
269
    for (Arg *A : filtered_reverse(Ids...))
270
      return A;
271
    return nullptr;
272
  }
273
 
274
  /// getArgString - Return the input argument string at \p Index.
275
  virtual const char *getArgString(unsigned Index) const = 0;
276
 
277
  /// getNumInputArgStrings - Return the number of original argument strings,
278
  /// which are guaranteed to be the first strings in the argument string
279
  /// list.
280
  virtual unsigned getNumInputArgStrings() const = 0;
281
 
282
  /// @}
283
  /// @name Argument Lookup Utilities
284
  /// @{
285
 
286
  /// getLastArgValue - Return the value of the last argument, or a default.
287
  StringRef getLastArgValue(OptSpecifier Id, StringRef Default = "") const;
288
 
289
  /// getAllArgValues - Get the values of all instances of the given argument
290
  /// as strings.
291
  std::vector<std::string> getAllArgValues(OptSpecifier Id) const;
292
 
293
  /// @}
294
  /// @name Translation Utilities
295
  /// @{
296
 
297
  /// hasFlag - Given an option \p Pos and its negative form \p Neg, return
298
  /// true if the option is present, false if the negation is present, and
299
  /// \p Default if neither option is given. If both the option and its
300
  /// negation are present, the last one wins.
301
  bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const;
302
 
303
  /// hasFlag - Given an option \p Pos, an alias \p PosAlias and its negative
304
  /// form \p Neg, return true if the option or its alias is present, false if
305
  /// the negation is present, and \p Default if none of the options are
306
  /// given. If multiple options are present, the last one wins.
307
  bool hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg,
308
               bool Default) const;
309
 
310
  /// Given an option Pos and its negative form Neg, render the option if Pos is
311
  /// present.
312
  void addOptInFlag(ArgStringList &Output, OptSpecifier Pos,
313
                    OptSpecifier Neg) const;
314
  /// Render the option if Neg is present.
315
  void addOptOutFlag(ArgStringList &Output, OptSpecifier Pos,
316
                     OptSpecifier Neg) const {
317
    addOptInFlag(Output, Neg, Pos);
318
  }
319
 
320
  /// Render only the last argument match \p Id0, if present.
321
  template<typename ...OptSpecifiers>
322
  void AddLastArg(ArgStringList &Output, OptSpecifiers ...Ids) const {
323
    if (Arg *A = getLastArg(Ids...)) // Calls claim() on all Ids's Args.
324
      A->render(*this, Output);
325
  }
326
 
327
  /// AddAllArgsExcept - Render all arguments matching any of the given ids
328
  /// and not matching any of the excluded ids.
329
  void AddAllArgsExcept(ArgStringList &Output, ArrayRef<OptSpecifier> Ids,
330
                        ArrayRef<OptSpecifier> ExcludeIds) const;
331
  /// AddAllArgs - Render all arguments matching any of the given ids.
332
  void AddAllArgs(ArgStringList &Output, ArrayRef<OptSpecifier> Ids) const;
333
 
334
  /// AddAllArgs - Render all arguments matching the given ids.
335
  void AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
336
                  OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
337
 
338
  /// AddAllArgValues - Render the argument values of all arguments
339
  /// matching the given ids.
340
  void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
341
                       OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
342
 
343
  /// AddAllArgsTranslated - Render all the arguments matching the
344
  /// given ids, but forced to separate args and using the provided
345
  /// name instead of the first option value.
346
  ///
347
  /// \param Joined - If true, render the argument as joined with
348
  /// the option specifier.
349
  void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
350
                            const char *Translation,
351
                            bool Joined = false) const;
352
 
353
  /// ClaimAllArgs - Claim all arguments which match the given
354
  /// option id.
355
  void ClaimAllArgs(OptSpecifier Id0) const;
356
 
357
  /// ClaimAllArgs - Claim all arguments.
358
  ///
359
  void ClaimAllArgs() const;
360
  /// @}
361
  /// @name Arg Synthesis
362
  /// @{
363
 
364
  /// Construct a constant string pointer whose
365
  /// lifetime will match that of the ArgList.
366
  virtual const char *MakeArgStringRef(StringRef Str) const = 0;
367
  const char *MakeArgString(const Twine &Str) const {
368
    SmallString<256> Buf;
369
    return MakeArgStringRef(Str.toStringRef(Buf));
370
  }
371
 
372
  /// Create an arg string for (\p LHS + \p RHS), reusing the
373
  /// string at \p Index if possible.
374
  const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS,
375
                                        StringRef RHS) const;
376
 
377
  void print(raw_ostream &O) const;
378
  void dump() const;
379
 
380
  /// @}
381
};
382
 
383
class InputArgList final : public ArgList {
384
private:
385
  /// List of argument strings used by the contained Args.
386
  ///
387
  /// This is mutable since we treat the ArgList as being the list
388
  /// of Args, and allow routines to add new strings (to have a
389
  /// convenient place to store the memory) via MakeIndex.
390
  mutable ArgStringList ArgStrings;
391
 
392
  /// Strings for synthesized arguments.
393
  ///
394
  /// This is mutable since we treat the ArgList as being the list
395
  /// of Args, and allow routines to add new strings (to have a
396
  /// convenient place to store the memory) via MakeIndex.
397
  mutable std::list<std::string> SynthesizedStrings;
398
 
399
  /// The number of original input argument strings.
400
  unsigned NumInputArgStrings;
401
 
402
  /// Release allocated arguments.
403
  void releaseMemory();
404
 
405
public:
406
  InputArgList() : NumInputArgStrings(0) {}
407
 
408
  InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
409
 
410
  InputArgList(InputArgList &&RHS)
411
      : ArgList(std::move(RHS)), ArgStrings(std::move(RHS.ArgStrings)),
412
        SynthesizedStrings(std::move(RHS.SynthesizedStrings)),
413
        NumInputArgStrings(RHS.NumInputArgStrings) {}
414
 
415
  InputArgList &operator=(InputArgList &&RHS) {
416
    releaseMemory();
417
    ArgList::operator=(std::move(RHS));
418
    ArgStrings = std::move(RHS.ArgStrings);
419
    SynthesizedStrings = std::move(RHS.SynthesizedStrings);
420
    NumInputArgStrings = RHS.NumInputArgStrings;
421
    return *this;
422
  }
423
 
424
  ~InputArgList() { releaseMemory(); }
425
 
426
  const char *getArgString(unsigned Index) const override {
427
    return ArgStrings[Index];
428
  }
429
 
430
  void replaceArgString(unsigned Index, const Twine &S) {
431
    ArgStrings[Index] = MakeArgString(S);
432
  }
433
 
434
  unsigned getNumInputArgStrings() const override {
435
    return NumInputArgStrings;
436
  }
437
 
438
  /// @name Arg Synthesis
439
  /// @{
440
 
441
public:
442
  /// MakeIndex - Get an index for the given string(s).
443
  unsigned MakeIndex(StringRef String0) const;
444
  unsigned MakeIndex(StringRef String0, StringRef String1) const;
445
 
446
  using ArgList::MakeArgString;
447
  const char *MakeArgStringRef(StringRef Str) const override;
448
 
449
  /// @}
450
};
451
 
452
/// DerivedArgList - An ordered collection of driver arguments,
453
/// whose storage may be in another argument list.
454
class DerivedArgList final : public ArgList {
455
  const InputArgList &BaseArgs;
456
 
457
  /// The list of arguments we synthesized.
458
  mutable SmallVector<std::unique_ptr<Arg>, 16> SynthesizedArgs;
459
 
460
public:
461
  /// Construct a new derived arg list from \p BaseArgs.
462
  DerivedArgList(const InputArgList &BaseArgs);
463
 
464
  const char *getArgString(unsigned Index) const override {
465
    return BaseArgs.getArgString(Index);
466
  }
467
 
468
  unsigned getNumInputArgStrings() const override {
469
    return BaseArgs.getNumInputArgStrings();
470
  }
471
 
472
  const InputArgList &getBaseArgs() const {
473
    return BaseArgs;
474
  }
475
 
476
  /// @name Arg Synthesis
477
  /// @{
478
 
479
  /// AddSynthesizedArg - Add a argument to the list of synthesized arguments
480
  /// (to be freed).
481
  void AddSynthesizedArg(Arg *A);
482
 
483
  using ArgList::MakeArgString;
484
  const char *MakeArgStringRef(StringRef Str) const override;
485
 
486
  /// AddFlagArg - Construct a new FlagArg for the given option \p Id and
487
  /// append it to the argument list.
488
  void AddFlagArg(const Arg *BaseArg, const Option Opt) {
489
    append(MakeFlagArg(BaseArg, Opt));
490
  }
491
 
492
  /// AddPositionalArg - Construct a new Positional arg for the given option
493
  /// \p Id, with the provided \p Value and append it to the argument
494
  /// list.
495
  void AddPositionalArg(const Arg *BaseArg, const Option Opt,
496
                        StringRef Value) {
497
    append(MakePositionalArg(BaseArg, Opt, Value));
498
  }
499
 
500
  /// AddSeparateArg - Construct a new Positional arg for the given option
501
  /// \p Id, with the provided \p Value and append it to the argument
502
  /// list.
503
  void AddSeparateArg(const Arg *BaseArg, const Option Opt,
504
                      StringRef Value) {
505
    append(MakeSeparateArg(BaseArg, Opt, Value));
506
  }
507
 
508
  /// AddJoinedArg - Construct a new Positional arg for the given option
509
  /// \p Id, with the provided \p Value and append it to the argument list.
510
  void AddJoinedArg(const Arg *BaseArg, const Option Opt,
511
                    StringRef Value) {
512
    append(MakeJoinedArg(BaseArg, Opt, Value));
513
  }
514
 
515
  /// MakeFlagArg - Construct a new FlagArg for the given option \p Id.
516
  Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const;
517
 
518
  /// MakePositionalArg - Construct a new Positional arg for the
519
  /// given option \p Id, with the provided \p Value.
520
  Arg *MakePositionalArg(const Arg *BaseArg, const Option Opt,
521
                          StringRef Value) const;
522
 
523
  /// MakeSeparateArg - Construct a new Positional arg for the
524
  /// given option \p Id, with the provided \p Value.
525
  Arg *MakeSeparateArg(const Arg *BaseArg, const Option Opt,
526
                        StringRef Value) const;
527
 
528
  /// MakeJoinedArg - Construct a new Positional arg for the
529
  /// given option \p Id, with the provided \p Value.
530
  Arg *MakeJoinedArg(const Arg *BaseArg, const Option Opt,
531
                      StringRef Value) const;
532
 
533
  /// @}
534
};
535
 
536
} // end namespace opt
537
 
538
} // end namespace llvm
539
 
540
#endif // LLVM_OPTION_ARGLIST_H