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