Option.h revision bcf6a8025aa50f3f28cfbd0470cf3e8f5cffbab2
1//===--- Option.h - Abstract Driver Options ---------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef CLANG_DRIVER_OPTION_H_
11#define CLANG_DRIVER_OPTION_H_
12
13#include "clang/Driver/OptSpecifier.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/Support/Casting.h"
16using llvm::isa;
17using llvm::cast;
18using llvm::cast_or_null;
19using llvm::dyn_cast;
20using llvm::dyn_cast_or_null;
21
22namespace clang {
23namespace driver {
24  class Arg;
25  class ArgList;
26  class OptionGroup;
27
28  /// Option - Abstract representation for a single form of driver
29  /// argument.
30  ///
31  /// An Option class represents a form of option that the driver
32  /// takes, for example how many arguments the option has and how
33  /// they can be provided. Individual option instances store
34  /// additional information about what group the option is a member
35  /// of (if any), if the option is an alias, and a number of
36  /// flags. At runtime the driver parses the command line into
37  /// concrete Arg instances, each of which corresponds to a
38  /// particular Option instance.
39  class Option {
40  public:
41    enum OptionClass {
42      GroupClass = 0,
43      InputClass,
44      UnknownClass,
45      FlagClass,
46      JoinedClass,
47      SeparateClass,
48      CommaJoinedClass,
49      MultiArgClass,
50      JoinedOrSeparateClass,
51      JoinedAndSeparateClass
52    };
53
54    enum RenderStyleKind {
55      RenderCommaJoinedStyle,
56      RenderJoinedStyle,
57      RenderSeparateStyle,
58      RenderValuesStyle
59    };
60
61  private:
62    OptionClass Kind;
63
64    /// The option ID.
65    OptSpecifier ID;
66
67    /// The option name.
68    llvm::StringRef Name;
69
70    /// Group this option is a member of, if any.
71    const OptionGroup *Group;
72
73    /// Option that this is an alias for, if any.
74    const Option *Alias;
75
76    /// Unsupported options will be rejected.
77    bool Unsupported : 1;
78
79    /// Treat this option like a linker input?
80    bool LinkerInput : 1;
81
82    /// When rendering as an input, don't render the option.
83
84    // FIXME: We should ditch the render/renderAsInput distinction.
85    bool NoOptAsInput : 1;
86
87    /// The style to using when rendering arguments parsed by this option.
88    unsigned RenderStyle : 2;
89
90    /// This option is only consumed by the driver.
91    bool DriverOption : 1;
92
93    /// This option should not report argument unused errors.
94    bool NoArgumentUnused : 1;
95
96    /// This option should not be implicitly forwarded.
97    bool NoForward : 1;
98
99  protected:
100    Option(OptionClass Kind, OptSpecifier ID, const char *Name,
101           const OptionGroup *Group, const Option *Alias);
102  public:
103    virtual ~Option();
104
105    unsigned getID() const { return ID.getID(); }
106    OptionClass getKind() const { return Kind; }
107    llvm::StringRef getName() const { return Name; }
108    const OptionGroup *getGroup() const { return Group; }
109    const Option *getAlias() const { return Alias; }
110
111    bool isUnsupported() const { return Unsupported; }
112    void setUnsupported(bool Value) { Unsupported = Value; }
113
114    bool isLinkerInput() const { return LinkerInput; }
115    void setLinkerInput(bool Value) { LinkerInput = Value; }
116
117    bool hasNoOptAsInput() const { return NoOptAsInput; }
118    void setNoOptAsInput(bool Value) { NoOptAsInput = Value; }
119
120    RenderStyleKind getRenderStyle() const {
121      return RenderStyleKind(RenderStyle);
122    }
123    void setRenderStyle(RenderStyleKind Value) { RenderStyle = Value; }
124
125    bool isDriverOption() const { return DriverOption; }
126    void setDriverOption(bool Value) { DriverOption = Value; }
127
128    bool hasNoArgumentUnused() const { return NoArgumentUnused; }
129    void setNoArgumentUnused(bool Value) { NoArgumentUnused = Value; }
130
131    bool hasNoForward() const { return NoForward; }
132    void setNoForward(bool Value) { NoForward = Value; }
133
134    bool hasForwardToGCC() const {
135      return !NoForward && !DriverOption && !LinkerInput;
136    }
137
138    /// getUnaliasedOption - Return the final option this option
139    /// aliases (itself, if the option has no alias).
140    const Option *getUnaliasedOption() const {
141      if (Alias) return Alias->getUnaliasedOption();
142      return this;
143    }
144
145    /// getRenderName - Return the name to use when rendering this
146    /// option.
147    llvm::StringRef getRenderName() const {
148      return getUnaliasedOption()->getName();
149    }
150
151    /// matches - Predicate for whether this option is part of the
152    /// given option (which may be a group).
153    ///
154    /// Note that matches against options which are an alias should never be
155    /// done -- aliases do not participate in matching and so such a query will
156    /// always be false.
157    bool matches(OptSpecifier ID) const;
158
159    /// accept - Potentially accept the current argument, returning a
160    /// new Arg instance, or 0 if the option does not accept this
161    /// argument (or the argument is missing values).
162    ///
163    /// If the option accepts the current argument, accept() sets
164    /// Index to the position where argument parsing should resume
165    /// (even if the argument is missing values).
166    virtual Arg *accept(const ArgList &Args, unsigned &Index) const = 0;
167
168    void dump() const;
169
170    static bool classof(const Option *) { return true; }
171  };
172
173  /// OptionGroup - A set of options which are can be handled uniformly
174  /// by the driver.
175  class OptionGroup : public Option {
176  public:
177    OptionGroup(OptSpecifier ID, const char *Name, const OptionGroup *Group);
178
179    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
180
181    static bool classof(const Option *O) {
182      return O->getKind() == Option::GroupClass;
183    }
184    static bool classof(const OptionGroup *) { return true; }
185  };
186
187  // Dummy option classes.
188
189  /// InputOption - Dummy option class for representing driver inputs.
190  class InputOption : public Option {
191  public:
192    InputOption(OptSpecifier ID);
193
194    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
195
196    static bool classof(const Option *O) {
197      return O->getKind() == Option::InputClass;
198    }
199    static bool classof(const InputOption *) { return true; }
200  };
201
202  /// UnknownOption - Dummy option class for represent unknown arguments.
203  class UnknownOption : public Option {
204  public:
205    UnknownOption(OptSpecifier ID);
206
207    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
208
209    static bool classof(const Option *O) {
210      return O->getKind() == Option::UnknownClass;
211    }
212    static bool classof(const UnknownOption *) { return true; }
213  };
214
215  // Normal options.
216
217  class FlagOption : public Option {
218  public:
219    FlagOption(OptSpecifier ID, const char *Name, const OptionGroup *Group,
220               const Option *Alias);
221
222    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
223
224    static bool classof(const Option *O) {
225      return O->getKind() == Option::FlagClass;
226    }
227    static bool classof(const FlagOption *) { return true; }
228  };
229
230  class JoinedOption : public Option {
231  public:
232    JoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group,
233                 const Option *Alias);
234
235    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
236
237    static bool classof(const Option *O) {
238      return O->getKind() == Option::JoinedClass;
239    }
240    static bool classof(const JoinedOption *) { return true; }
241  };
242
243  class SeparateOption : public Option {
244  public:
245    SeparateOption(OptSpecifier ID, const char *Name,
246                   const OptionGroup *Group, const Option *Alias);
247
248    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
249
250    static bool classof(const Option *O) {
251      return O->getKind() == Option::SeparateClass;
252    }
253    static bool classof(const SeparateOption *) { return true; }
254  };
255
256  class CommaJoinedOption : public Option {
257  public:
258    CommaJoinedOption(OptSpecifier ID, const char *Name,
259                      const OptionGroup *Group, const Option *Alias);
260
261    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
262
263    static bool classof(const Option *O) {
264      return O->getKind() == Option::CommaJoinedClass;
265    }
266    static bool classof(const CommaJoinedOption *) { return true; }
267  };
268
269  // FIXME: Fold MultiArgOption into SeparateOption?
270
271  /// MultiArgOption - An option which takes multiple arguments (these
272  /// are always separate arguments).
273  class MultiArgOption : public Option {
274    unsigned NumArgs;
275
276  public:
277    MultiArgOption(OptSpecifier ID, const char *Name, const OptionGroup *Group,
278                   const Option *Alias, unsigned NumArgs);
279
280    unsigned getNumArgs() const { return NumArgs; }
281
282    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
283
284    static bool classof(const Option *O) {
285      return O->getKind() == Option::MultiArgClass;
286    }
287    static bool classof(const MultiArgOption *) { return true; }
288  };
289
290  /// JoinedOrSeparateOption - An option which either literally
291  /// prefixes its (non-empty) value, or is follwed by a value.
292  class JoinedOrSeparateOption : public Option {
293  public:
294    JoinedOrSeparateOption(OptSpecifier ID, const char *Name,
295                           const OptionGroup *Group, const Option *Alias);
296
297    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
298
299    static bool classof(const Option *O) {
300      return O->getKind() == Option::JoinedOrSeparateClass;
301    }
302    static bool classof(const JoinedOrSeparateOption *) { return true; }
303  };
304
305  /// JoinedAndSeparateOption - An option which literally prefixes its
306  /// value and is followed by another value.
307  class JoinedAndSeparateOption : public Option {
308  public:
309    JoinedAndSeparateOption(OptSpecifier ID, const char *Name,
310                            const OptionGroup *Group, const Option *Alias);
311
312    virtual Arg *accept(const ArgList &Args, unsigned &Index) const;
313
314    static bool classof(const Option *O) {
315      return O->getKind() == Option::JoinedAndSeparateClass;
316    }
317    static bool classof(const JoinedAndSeparateOption *) { return true; }
318  };
319
320} // end namespace driver
321} // end namespace clang
322
323#endif
324