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