Home | History | Annotate | Download | only in Driver
      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 
     17 namespace clang {
     18 namespace 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