1 //===--- ArgList.h - Argument List Management ----------*- 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_ARGLIST_H_ 11 #define CLANG_DRIVER_ARGLIST_H_ 12 13 #include "clang/Driver/OptSpecifier.h" 14 #include "clang/Driver/Util.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/StringRef.h" 17 18 #include <list> 19 #include <string> 20 #include <vector> 21 22 namespace llvm { 23 class Twine; 24 } 25 26 namespace clang { 27 class Diagnostic; 28 29 namespace driver { 30 class Arg; 31 class ArgList; 32 class Option; 33 34 /// arg_iterator - Iterates through arguments stored inside an ArgList. 35 class arg_iterator { 36 /// The current argument. 37 llvm::SmallVectorImpl<Arg*>::const_iterator Current; 38 39 /// The argument list we are iterating over. 40 const ArgList &Args; 41 42 /// Optional filters on the arguments which will be match. Most clients 43 /// should never want to iterate over arguments without filters, so we won't 44 /// bother to factor this into two separate iterator implementations. 45 // 46 // FIXME: Make efficient; the idea is to provide efficient iteration over 47 // all arguments which match a particular id and then just provide an 48 // iterator combinator which takes multiple iterators which can be 49 // efficiently compared and returns them in order. 50 OptSpecifier Id0, Id1, Id2; 51 52 void SkipToNextArg(); 53 54 public: 55 typedef Arg * const * value_type; 56 typedef Arg * const & reference; 57 typedef Arg * const * pointer; 58 typedef std::forward_iterator_tag iterator_category; 59 typedef std::ptrdiff_t difference_type; 60 61 arg_iterator(llvm::SmallVectorImpl<Arg*>::const_iterator it, 62 const ArgList &_Args, OptSpecifier _Id0 = 0U, 63 OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U) Current(it)64 : Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) { 65 SkipToNextArg(); 66 } 67 68 operator const Arg*() { return *Current; } 69 reference operator*() const { return *Current; } 70 pointer operator->() const { return Current; } 71 72 arg_iterator &operator++() { 73 ++Current; 74 SkipToNextArg(); 75 return *this; 76 } 77 78 arg_iterator operator++(int) { 79 arg_iterator tmp(*this); 80 ++(*this); 81 return tmp; 82 } 83 84 friend bool operator==(arg_iterator LHS, arg_iterator RHS) { 85 return LHS.Current == RHS.Current; 86 } 87 friend bool operator!=(arg_iterator LHS, arg_iterator RHS) { 88 return !(LHS == RHS); 89 } 90 }; 91 92 /// ArgList - Ordered collection of driver arguments. 93 /// 94 /// The ArgList class manages a list of Arg instances as well as 95 /// auxiliary data and convenience methods to allow Tools to quickly 96 /// check for the presence of Arg instances for a particular Option 97 /// and to iterate over groups of arguments. 98 class ArgList { 99 private: 100 ArgList(const ArgList &); // DO NOT IMPLEMENT 101 void operator=(const ArgList &); // DO NOT IMPLEMENT 102 103 public: 104 typedef llvm::SmallVector<Arg*, 16> arglist_type; 105 typedef arglist_type::iterator iterator; 106 typedef arglist_type::const_iterator const_iterator; 107 typedef arglist_type::reverse_iterator reverse_iterator; 108 typedef arglist_type::const_reverse_iterator const_reverse_iterator; 109 110 private: 111 /// The internal list of arguments. 112 arglist_type Args; 113 114 protected: 115 ArgList(); 116 117 public: 118 virtual ~ArgList(); 119 120 /// @name Arg Access 121 /// @{ 122 123 /// append - Append \arg A to the arg list. 124 void append(Arg *A); 125 getArgs()126 arglist_type &getArgs() { return Args; } getArgs()127 const arglist_type &getArgs() const { return Args; } 128 size()129 unsigned size() const { return Args.size(); } 130 131 /// @} 132 /// @name Arg Iteration 133 /// @{ 134 begin()135 iterator begin() { return Args.begin(); } end()136 iterator end() { return Args.end(); } 137 rbegin()138 reverse_iterator rbegin() { return Args.rbegin(); } rend()139 reverse_iterator rend() { return Args.rend(); } 140 begin()141 const_iterator begin() const { return Args.begin(); } end()142 const_iterator end() const { return Args.end(); } 143 rbegin()144 const_reverse_iterator rbegin() const { return Args.rbegin(); } rend()145 const_reverse_iterator rend() const { return Args.rend(); } 146 147 arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U, 148 OptSpecifier Id2 = 0U) const { 149 return arg_iterator(Args.begin(), *this, Id0, Id1, Id2); 150 } filtered_end()151 arg_iterator filtered_end() const { 152 return arg_iterator(Args.end(), *this); 153 } 154 155 /// @} 156 /// @name Arg Access 157 /// @{ 158 159 /// hasArg - Does the arg list contain any option matching \arg Id. 160 /// 161 /// \arg Claim Whether the argument should be claimed, if it exists. hasArgNoClaim(OptSpecifier Id)162 bool hasArgNoClaim(OptSpecifier Id) const { 163 return getLastArgNoClaim(Id) != 0; 164 } hasArg(OptSpecifier Id)165 bool hasArg(OptSpecifier Id) const { 166 return getLastArg(Id) != 0; 167 } hasArg(OptSpecifier Id0,OptSpecifier Id1)168 bool hasArg(OptSpecifier Id0, OptSpecifier Id1) const { 169 return getLastArg(Id0, Id1) != 0; 170 } hasArg(OptSpecifier Id0,OptSpecifier Id1,OptSpecifier Id2)171 bool hasArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const { 172 return getLastArg(Id0, Id1, Id2) != 0; 173 } 174 175 /// getLastArg - Return the last argument matching \arg Id, or null. 176 /// 177 /// \arg Claim Whether the argument should be claimed, if it exists. 178 Arg *getLastArgNoClaim(OptSpecifier Id) const; 179 Arg *getLastArg(OptSpecifier Id) const; 180 Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const; 181 Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const; 182 Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, 183 OptSpecifier Id3) const; 184 185 /// getArgString - Return the input argument string at \arg Index. 186 virtual const char *getArgString(unsigned Index) const = 0; 187 188 /// getNumInputArgStrings - Return the number of original argument strings, 189 /// which are guaranteed to be the first strings in the argument string 190 /// list. 191 virtual unsigned getNumInputArgStrings() const = 0; 192 193 /// @} 194 /// @name Argument Lookup Utilities 195 /// @{ 196 197 /// getLastArgValue - Return the value of the last argument, or a default. 198 llvm::StringRef getLastArgValue(OptSpecifier Id, 199 llvm::StringRef Default = "") const; 200 201 /// getLastArgValue - Return the value of the last argument as an integer, 202 /// or a default. Emits an error if the argument is given, but non-integral. 203 int getLastArgIntValue(OptSpecifier Id, int Default, 204 Diagnostic &Diags) const; 205 206 /// getAllArgValues - Get the values of all instances of the given argument 207 /// as strings. 208 std::vector<std::string> getAllArgValues(OptSpecifier Id) const; 209 210 /// @} 211 /// @name Translation Utilities 212 /// @{ 213 214 /// hasFlag - Given an option \arg Pos and its negative form \arg 215 /// Neg, return true if the option is present, false if the 216 /// negation is present, and \arg Default if neither option is 217 /// given. If both the option and its negation are present, the 218 /// last one wins. 219 bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const; 220 221 /// AddLastArg - Render only the last argument match \arg Id0, if 222 /// present. 223 void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const; 224 225 /// AddAllArgs - Render all arguments matching the given ids. 226 void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, 227 OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; 228 229 /// AddAllArgValues - Render the argument values of all arguments 230 /// matching the given ids. 231 void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, 232 OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; 233 234 /// AddAllArgsTranslated - Render all the arguments matching the 235 /// given ids, but forced to separate args and using the provided 236 /// name instead of the first option value. 237 /// 238 /// \param Joined - If true, render the argument as joined with 239 /// the option specifier. 240 void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, 241 const char *Translation, 242 bool Joined = false) const; 243 244 /// ClaimAllArgs - Claim all arguments which match the given 245 /// option id. 246 void ClaimAllArgs(OptSpecifier Id0) const; 247 248 /// @} 249 /// @name Arg Synthesis 250 /// @{ 251 252 /// MakeArgString - Construct a constant string pointer whose 253 /// lifetime will match that of the ArgList. 254 virtual const char *MakeArgString(llvm::StringRef Str) const = 0; MakeArgString(const char * Str)255 const char *MakeArgString(const char *Str) const { 256 return MakeArgString(llvm::StringRef(Str)); 257 } MakeArgString(std::string Str)258 const char *MakeArgString(std::string Str) const { 259 return MakeArgString(llvm::StringRef(Str)); 260 } 261 const char *MakeArgString(const llvm::Twine &Str) const; 262 263 /// \brief Create an arg string for (\arg LHS + \arg RHS), reusing the 264 /// string at \arg Index if possible. 265 const char *GetOrMakeJoinedArgString(unsigned Index, llvm::StringRef LHS, 266 llvm::StringRef RHS) const; 267 268 /// @} 269 }; 270 271 class InputArgList : public ArgList { 272 private: 273 /// List of argument strings used by the contained Args. 274 /// 275 /// This is mutable since we treat the ArgList as being the list 276 /// of Args, and allow routines to add new strings (to have a 277 /// convenient place to store the memory) via MakeIndex. 278 mutable ArgStringList ArgStrings; 279 280 /// Strings for synthesized arguments. 281 /// 282 /// This is mutable since we treat the ArgList as being the list 283 /// of Args, and allow routines to add new strings (to have a 284 /// convenient place to store the memory) via MakeIndex. 285 mutable std::list<std::string> SynthesizedStrings; 286 287 /// The number of original input argument strings. 288 unsigned NumInputArgStrings; 289 290 public: 291 InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); 292 ~InputArgList(); 293 getArgString(unsigned Index)294 virtual const char *getArgString(unsigned Index) const { 295 return ArgStrings[Index]; 296 } 297 getNumInputArgStrings()298 virtual unsigned getNumInputArgStrings() const { 299 return NumInputArgStrings; 300 } 301 302 /// @name Arg Synthesis 303 /// @{ 304 305 public: 306 /// MakeIndex - Get an index for the given string(s). 307 unsigned MakeIndex(llvm::StringRef String0) const; 308 unsigned MakeIndex(llvm::StringRef String0, llvm::StringRef String1) const; 309 310 virtual const char *MakeArgString(llvm::StringRef Str) const; 311 312 /// @} 313 }; 314 315 /// DerivedArgList - An ordered collection of driver arguments, 316 /// whose storage may be in another argument list. 317 class DerivedArgList : public ArgList { 318 const InputArgList &BaseArgs; 319 320 /// The list of arguments we synthesized. 321 mutable arglist_type SynthesizedArgs; 322 323 public: 324 /// Construct a new derived arg list from \arg BaseArgs. 325 DerivedArgList(const InputArgList &BaseArgs); 326 ~DerivedArgList(); 327 getArgString(unsigned Index)328 virtual const char *getArgString(unsigned Index) const { 329 return BaseArgs.getArgString(Index); 330 } 331 getNumInputArgStrings()332 virtual unsigned getNumInputArgStrings() const { 333 return BaseArgs.getNumInputArgStrings(); 334 } 335 getBaseArgs()336 const InputArgList &getBaseArgs() const { 337 return BaseArgs; 338 } 339 340 /// @name Arg Synthesis 341 /// @{ 342 343 /// AddSynthesizedArg - Add a argument to the list of synthesized arguments 344 /// (to be freed). AddSynthesizedArg(Arg * A)345 void AddSynthesizedArg(Arg *A) { 346 SynthesizedArgs.push_back(A); 347 } 348 349 virtual const char *MakeArgString(llvm::StringRef Str) const; 350 351 /// AddFlagArg - Construct a new FlagArg for the given option \arg Id and 352 /// append it to the argument list. AddFlagArg(const Arg * BaseArg,const Option * Opt)353 void AddFlagArg(const Arg *BaseArg, const Option *Opt) { 354 append(MakeFlagArg(BaseArg, Opt)); 355 } 356 357 /// AddPositionalArg - Construct a new Positional arg for the given option 358 /// \arg Id, with the provided \arg Value and append it to the argument 359 /// list. AddPositionalArg(const Arg * BaseArg,const Option * Opt,llvm::StringRef Value)360 void AddPositionalArg(const Arg *BaseArg, const Option *Opt, 361 llvm::StringRef Value) { 362 append(MakePositionalArg(BaseArg, Opt, Value)); 363 } 364 365 366 /// AddSeparateArg - Construct a new Positional arg for the given option 367 /// \arg Id, with the provided \arg Value and append it to the argument 368 /// list. AddSeparateArg(const Arg * BaseArg,const Option * Opt,llvm::StringRef Value)369 void AddSeparateArg(const Arg *BaseArg, const Option *Opt, 370 llvm::StringRef Value) { 371 append(MakeSeparateArg(BaseArg, Opt, Value)); 372 } 373 374 375 /// AddJoinedArg - Construct a new Positional arg for the given option \arg 376 /// Id, with the provided \arg Value and append it to the argument list. AddJoinedArg(const Arg * BaseArg,const Option * Opt,llvm::StringRef Value)377 void AddJoinedArg(const Arg *BaseArg, const Option *Opt, 378 llvm::StringRef Value) { 379 append(MakeJoinedArg(BaseArg, Opt, Value)); 380 } 381 382 383 /// MakeFlagArg - Construct a new FlagArg for the given option 384 /// \arg Id. 385 Arg *MakeFlagArg(const Arg *BaseArg, const Option *Opt) const; 386 387 /// MakePositionalArg - Construct a new Positional arg for the 388 /// given option \arg Id, with the provided \arg Value. 389 Arg *MakePositionalArg(const Arg *BaseArg, const Option *Opt, 390 llvm::StringRef Value) const; 391 392 /// MakeSeparateArg - Construct a new Positional arg for the 393 /// given option \arg Id, with the provided \arg Value. 394 Arg *MakeSeparateArg(const Arg *BaseArg, const Option *Opt, 395 llvm::StringRef Value) const; 396 397 /// MakeJoinedArg - Construct a new Positional arg for the 398 /// given option \arg Id, with the provided \arg Value. 399 Arg *MakeJoinedArg(const Arg *BaseArg, const Option *Opt, 400 llvm::StringRef Value) const; 401 402 /// @} 403 }; 404 405 } // end namespace driver 406 } // end namespace clang 407 408 #endif 409