|  | //===--- Option.h - Abstract Driver Options ---------------------*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef CLANG_DRIVER_OPTION_H_ | 
|  | #define CLANG_DRIVER_OPTION_H_ | 
|  |  | 
|  | #include "clang/Driver/OptSpecifier.h" | 
|  | #include "llvm/ADT/StringRef.h" | 
|  | #include "llvm/Support/Casting.h" | 
|  | using llvm::isa; | 
|  | using llvm::cast; | 
|  | using llvm::cast_or_null; | 
|  | using llvm::dyn_cast; | 
|  | using llvm::dyn_cast_or_null; | 
|  |  | 
|  | namespace clang { | 
|  | namespace driver { | 
|  | class Arg; | 
|  | class ArgList; | 
|  | class OptionGroup; | 
|  |  | 
|  | /// Option - Abstract representation for a single form of driver | 
|  | /// argument. | 
|  | /// | 
|  | /// An Option class represents a form of option that the driver | 
|  | /// takes, for example how many arguments the option has and how | 
|  | /// they can be provided. Individual option instances store | 
|  | /// additional information about what group the option is a member | 
|  | /// of (if any), if the option is an alias, and a number of | 
|  | /// flags. At runtime the driver parses the command line into | 
|  | /// concrete Arg instances, each of which corresponds to a | 
|  | /// particular Option instance. | 
|  | class Option { | 
|  | public: | 
|  | enum OptionClass { | 
|  | GroupClass = 0, | 
|  | InputClass, | 
|  | UnknownClass, | 
|  | FlagClass, | 
|  | JoinedClass, | 
|  | SeparateClass, | 
|  | CommaJoinedClass, | 
|  | MultiArgClass, | 
|  | JoinedOrSeparateClass, | 
|  | JoinedAndSeparateClass | 
|  | }; | 
|  |  | 
|  | enum RenderStyleKind { | 
|  | RenderCommaJoinedStyle, | 
|  | RenderJoinedStyle, | 
|  | RenderSeparateStyle, | 
|  | RenderValuesStyle | 
|  | }; | 
|  |  | 
|  | private: | 
|  | OptionClass Kind; | 
|  |  | 
|  | /// The option ID. | 
|  | OptSpecifier ID; | 
|  |  | 
|  | /// The option name. | 
|  | llvm::StringRef Name; | 
|  |  | 
|  | /// Group this option is a member of, if any. | 
|  | const OptionGroup *Group; | 
|  |  | 
|  | /// Option that this is an alias for, if any. | 
|  | const Option *Alias; | 
|  |  | 
|  | /// Unsupported options will be rejected. | 
|  | bool Unsupported : 1; | 
|  |  | 
|  | /// Treat this option like a linker input? | 
|  | bool LinkerInput : 1; | 
|  |  | 
|  | /// When rendering as an input, don't render the option. | 
|  |  | 
|  | // FIXME: We should ditch the render/renderAsInput distinction. | 
|  | bool NoOptAsInput : 1; | 
|  |  | 
|  | /// The style to using when rendering arguments parsed by this option. | 
|  | unsigned RenderStyle : 2; | 
|  |  | 
|  | /// This option is only consumed by the driver. | 
|  | bool DriverOption : 1; | 
|  |  | 
|  | /// This option should not report argument unused errors. | 
|  | bool NoArgumentUnused : 1; | 
|  |  | 
|  | /// This option should not be implicitly forwarded. | 
|  | bool NoForward : 1; | 
|  |  | 
|  | protected: | 
|  | Option(OptionClass Kind, OptSpecifier ID, const char *Name, | 
|  | const OptionGroup *Group, const Option *Alias); | 
|  | public: | 
|  | virtual ~Option(); | 
|  |  | 
|  | unsigned getID() const { return ID.getID(); } | 
|  | OptionClass getKind() const { return Kind; } | 
|  | llvm::StringRef getName() const { return Name; } | 
|  | const OptionGroup *getGroup() const { return Group; } | 
|  | const Option *getAlias() const { return Alias; } | 
|  |  | 
|  | bool isUnsupported() const { return Unsupported; } | 
|  | void setUnsupported(bool Value) { Unsupported = Value; } | 
|  |  | 
|  | bool isLinkerInput() const { return LinkerInput; } | 
|  | void setLinkerInput(bool Value) { LinkerInput = Value; } | 
|  |  | 
|  | bool hasNoOptAsInput() const { return NoOptAsInput; } | 
|  | void setNoOptAsInput(bool Value) { NoOptAsInput = Value; } | 
|  |  | 
|  | RenderStyleKind getRenderStyle() const { | 
|  | return RenderStyleKind(RenderStyle); | 
|  | } | 
|  | void setRenderStyle(RenderStyleKind Value) { RenderStyle = Value; } | 
|  |  | 
|  | bool isDriverOption() const { return DriverOption; } | 
|  | void setDriverOption(bool Value) { DriverOption = Value; } | 
|  |  | 
|  | bool hasNoArgumentUnused() const { return NoArgumentUnused; } | 
|  | void setNoArgumentUnused(bool Value) { NoArgumentUnused = Value; } | 
|  |  | 
|  | bool hasNoForward() const { return NoForward; } | 
|  | void setNoForward(bool Value) { NoForward = Value; } | 
|  |  | 
|  | bool hasForwardToGCC() const { | 
|  | return !NoForward && !DriverOption && !LinkerInput; | 
|  | } | 
|  |  | 
|  | /// getUnaliasedOption - Return the final option this option | 
|  | /// aliases (itself, if the option has no alias). | 
|  | const Option *getUnaliasedOption() const { | 
|  | if (Alias) return Alias->getUnaliasedOption(); | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /// getRenderName - Return the name to use when rendering this | 
|  | /// option. | 
|  | llvm::StringRef getRenderName() const { | 
|  | return getUnaliasedOption()->getName(); | 
|  | } | 
|  |  | 
|  | /// matches - Predicate for whether this option is part of the | 
|  | /// given option (which may be a group). | 
|  | /// | 
|  | /// Note that matches against options which are an alias should never be | 
|  | /// done -- aliases do not participate in matching and so such a query will | 
|  | /// always be false. | 
|  | bool matches(OptSpecifier ID) const; | 
|  |  | 
|  | /// accept - Potentially accept the current argument, returning a | 
|  | /// new Arg instance, or 0 if the option does not accept this | 
|  | /// argument (or the argument is missing values). | 
|  | /// | 
|  | /// If the option accepts the current argument, accept() sets | 
|  | /// Index to the position where argument parsing should resume | 
|  | /// (even if the argument is missing values). | 
|  | virtual Arg *accept(const ArgList &Args, unsigned &Index) const = 0; | 
|  |  | 
|  | void dump() const; | 
|  |  | 
|  | static bool classof(const Option *) { return true; } | 
|  | }; | 
|  |  | 
|  | /// OptionGroup - A set of options which are can be handled uniformly | 
|  | /// by the driver. | 
|  | class OptionGroup : public Option { | 
|  | public: | 
|  | OptionGroup(OptSpecifier ID, const char *Name, const OptionGroup *Group); | 
|  |  | 
|  | virtual Arg *accept(const ArgList &Args, unsigned &Index) const; | 
|  |  | 
|  | static bool classof(const Option *O) { | 
|  | return O->getKind() == Option::GroupClass; | 
|  | } | 
|  | static bool classof(const OptionGroup *) { return true; } | 
|  | }; | 
|  |  | 
|  | // Dummy option classes. | 
|  |  | 
|  | /// InputOption - Dummy option class for representing driver inputs. | 
|  | class InputOption : public Option { | 
|  | public: | 
|  | InputOption(OptSpecifier ID); | 
|  |  | 
|  | virtual Arg *accept(const ArgList &Args, unsigned &Index) const; | 
|  |  | 
|  | static bool classof(const Option *O) { | 
|  | return O->getKind() == Option::InputClass; | 
|  | } | 
|  | static bool classof(const InputOption *) { return true; } | 
|  | }; | 
|  |  | 
|  | /// UnknownOption - Dummy option class for represent unknown arguments. | 
|  | class UnknownOption : public Option { | 
|  | public: | 
|  | UnknownOption(OptSpecifier ID); | 
|  |  | 
|  | virtual Arg *accept(const ArgList &Args, unsigned &Index) const; | 
|  |  | 
|  | static bool classof(const Option *O) { | 
|  | return O->getKind() == Option::UnknownClass; | 
|  | } | 
|  | static bool classof(const UnknownOption *) { return true; } | 
|  | }; | 
|  |  | 
|  | // Normal options. | 
|  |  | 
|  | class FlagOption : public Option { | 
|  | public: | 
|  | FlagOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, | 
|  | const Option *Alias); | 
|  |  | 
|  | virtual Arg *accept(const ArgList &Args, unsigned &Index) const; | 
|  |  | 
|  | static bool classof(const Option *O) { | 
|  | return O->getKind() == Option::FlagClass; | 
|  | } | 
|  | static bool classof(const FlagOption *) { return true; } | 
|  | }; | 
|  |  | 
|  | class JoinedOption : public Option { | 
|  | public: | 
|  | JoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, | 
|  | const Option *Alias); | 
|  |  | 
|  | virtual Arg *accept(const ArgList &Args, unsigned &Index) const; | 
|  |  | 
|  | static bool classof(const Option *O) { | 
|  | return O->getKind() == Option::JoinedClass; | 
|  | } | 
|  | static bool classof(const JoinedOption *) { return true; } | 
|  | }; | 
|  |  | 
|  | class SeparateOption : public Option { | 
|  | public: | 
|  | SeparateOption(OptSpecifier ID, const char *Name, | 
|  | const OptionGroup *Group, const Option *Alias); | 
|  |  | 
|  | virtual Arg *accept(const ArgList &Args, unsigned &Index) const; | 
|  |  | 
|  | static bool classof(const Option *O) { | 
|  | return O->getKind() == Option::SeparateClass; | 
|  | } | 
|  | static bool classof(const SeparateOption *) { return true; } | 
|  | }; | 
|  |  | 
|  | class CommaJoinedOption : public Option { | 
|  | public: | 
|  | CommaJoinedOption(OptSpecifier ID, const char *Name, | 
|  | const OptionGroup *Group, const Option *Alias); | 
|  |  | 
|  | virtual Arg *accept(const ArgList &Args, unsigned &Index) const; | 
|  |  | 
|  | static bool classof(const Option *O) { | 
|  | return O->getKind() == Option::CommaJoinedClass; | 
|  | } | 
|  | static bool classof(const CommaJoinedOption *) { return true; } | 
|  | }; | 
|  |  | 
|  | // FIXME: Fold MultiArgOption into SeparateOption? | 
|  |  | 
|  | /// MultiArgOption - An option which takes multiple arguments (these | 
|  | /// are always separate arguments). | 
|  | class MultiArgOption : public Option { | 
|  | unsigned NumArgs; | 
|  |  | 
|  | public: | 
|  | MultiArgOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, | 
|  | const Option *Alias, unsigned NumArgs); | 
|  |  | 
|  | unsigned getNumArgs() const { return NumArgs; } | 
|  |  | 
|  | virtual Arg *accept(const ArgList &Args, unsigned &Index) const; | 
|  |  | 
|  | static bool classof(const Option *O) { | 
|  | return O->getKind() == Option::MultiArgClass; | 
|  | } | 
|  | static bool classof(const MultiArgOption *) { return true; } | 
|  | }; | 
|  |  | 
|  | /// JoinedOrSeparateOption - An option which either literally | 
|  | /// prefixes its (non-empty) value, or is follwed by a value. | 
|  | class JoinedOrSeparateOption : public Option { | 
|  | public: | 
|  | JoinedOrSeparateOption(OptSpecifier ID, const char *Name, | 
|  | const OptionGroup *Group, const Option *Alias); | 
|  |  | 
|  | virtual Arg *accept(const ArgList &Args, unsigned &Index) const; | 
|  |  | 
|  | static bool classof(const Option *O) { | 
|  | return O->getKind() == Option::JoinedOrSeparateClass; | 
|  | } | 
|  | static bool classof(const JoinedOrSeparateOption *) { return true; } | 
|  | }; | 
|  |  | 
|  | /// JoinedAndSeparateOption - An option which literally prefixes its | 
|  | /// value and is followed by another value. | 
|  | class JoinedAndSeparateOption : public Option { | 
|  | public: | 
|  | JoinedAndSeparateOption(OptSpecifier ID, const char *Name, | 
|  | const OptionGroup *Group, const Option *Alias); | 
|  |  | 
|  | virtual Arg *accept(const ArgList &Args, unsigned &Index) const; | 
|  |  | 
|  | static bool classof(const Option *O) { | 
|  | return O->getKind() == Option::JoinedAndSeparateClass; | 
|  | } | 
|  | static bool classof(const JoinedAndSeparateOption *) { return true; } | 
|  | }; | 
|  |  | 
|  | } // end namespace driver | 
|  | } // end namespace clang | 
|  |  | 
|  | #endif |