#define LLVM_OPTION_ARGLIST_H
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Option/Arg.h"
#include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/Option.h"
#include <list>
+#include <memory>
#include <string>
#include <vector>
namespace llvm {
namespace opt {
-class Arg;
class ArgList;
class Option;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
- arg_iterator(SmallVectorImpl<Arg*>::const_iterator it,
- const ArgList &_Args, OptSpecifier _Id0 = 0U,
- OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U)
- : Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) {
+ arg_iterator(SmallVectorImpl<Arg *>::const_iterator it, const ArgList &Args,
+ OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U,
+ OptSpecifier Id2 = 0U)
+ : Current(it), Args(Args), Id0(Id0), Id1(Id1), Id2(Id2) {
SkipToNextArg();
}
/// check for the presence of Arg instances for a particular Option
/// and to iterate over groups of arguments.
class ArgList {
-private:
- ArgList(const ArgList &) LLVM_DELETED_FUNCTION;
- void operator=(const ArgList &) LLVM_DELETED_FUNCTION;
-
public:
typedef SmallVector<Arg*, 16> arglist_type;
typedef arglist_type::iterator iterator;
arglist_type Args;
protected:
- ArgList();
+ // Make the default special members protected so they won't be used to slice
+ // derived objects, but can still be used by derived objects to implement
+ // their own special members.
+ ArgList() = default;
+ // Explicit move operations to ensure the container is cleared post-move
+ // otherwise it could lead to a double-delete in the case of moving of an
+ // InputArgList which deletes the contents of the container. If we could fix
+ // up the ownership here (delegate storage/ownership to the derived class so
+ // it can be a container of unique_ptr) this would be simpler.
+ ArgList(ArgList &&RHS) : Args(std::move(RHS.Args)) { RHS.Args.clear(); }
+ ArgList &operator=(ArgList &&RHS) {
+ Args = std::move(RHS.Args);
+ RHS.Args.clear();
+ return *this;
+ }
+ // Protect the dtor to ensure this type is never destroyed polymorphically.
+ ~ArgList() = default;
public:
- virtual ~ArgList();
/// @name Arg Access
/// @{
return arg_iterator(Args.end(), *this);
}
+ iterator_range<arg_iterator> filtered(OptSpecifier Id0 = 0U,
+ OptSpecifier Id1 = 0U,
+ OptSpecifier Id2 = 0U) const {
+ return make_range(filtered_begin(Id0, Id1, Id2), filtered_end());
+ }
+
/// @}
/// @name Arg Removal
/// @{
///
/// \p Claim Whether the argument should be claimed, if it exists.
bool hasArgNoClaim(OptSpecifier Id) const {
- return getLastArgNoClaim(Id) != 0;
+ return getLastArgNoClaim(Id) != nullptr;
}
bool hasArg(OptSpecifier Id) const {
- return getLastArg(Id) != 0;
+ return getLastArg(Id) != nullptr;
}
bool hasArg(OptSpecifier Id0, OptSpecifier Id1) const {
- return getLastArg(Id0, Id1) != 0;
+ return getLastArg(Id0, Id1) != nullptr;
}
bool hasArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const {
- return getLastArg(Id0, Id1, Id2) != 0;
+ return getLastArg(Id0, Id1, Id2) != nullptr;
}
/// getLastArg - Return the last argument matching \p Id, or null.
///
/// \p Claim Whether the argument should be claimed, if it exists.
Arg *getLastArgNoClaim(OptSpecifier Id) const;
+ Arg *getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1) const;
+ Arg *getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1,
+ OptSpecifier Id2) const;
+ Arg *getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
+ OptSpecifier Id3) const;
Arg *getLastArg(OptSpecifier Id) const;
Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const;
Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const;
/// negation are present, the last one wins.
bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const;
+ /// hasFlag - Given an option \p Pos, an alias \p PosAlias and its negative
+ /// form \p Neg, return true if the option or its alias is present, false if
+ /// the negation is present, and \p Default if none of the options are
+ /// given. If multiple options are present, the last one wins.
+ bool hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg,
+ bool Default = true) const;
+
/// AddLastArg - Render only the last argument match \p Id0, if present.
void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const;
+ void AddLastArg(ArgStringList &Output, OptSpecifier Id0,
+ OptSpecifier Id1) const;
+
+ /// AddAllArgs - Render all arguments matching any of the given ids.
+ void AddAllArgs(ArgStringList &Output, ArrayRef<OptSpecifier> Ids) const;
/// AddAllArgs - Render all arguments matching the given ids.
void AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
/// @name Arg Synthesis
/// @{
- /// MakeArgString - Construct a constant string pointer whose
+ /// Construct a constant string pointer whose
/// lifetime will match that of the ArgList.
- virtual const char *MakeArgString(StringRef Str) const = 0;
- const char *MakeArgString(const char *Str) const {
- return MakeArgString(StringRef(Str));
- }
- const char *MakeArgString(std::string Str) const {
- return MakeArgString(StringRef(Str));
+ virtual const char *MakeArgStringRef(StringRef Str) const = 0;
+ const char *MakeArgString(const Twine &Str) const {
+ SmallString<256> Buf;
+ return MakeArgStringRef(Str.toStringRef(Buf));
}
- const char *MakeArgString(const Twine &Str) const;
/// \brief Create an arg string for (\p LHS + \p RHS), reusing the
/// string at \p Index if possible.
/// @}
};
-class InputArgList : public ArgList {
+class InputArgList final : public ArgList {
private:
/// List of argument strings used by the contained Args.
///
/// The number of original input argument strings.
unsigned NumInputArgStrings;
+ /// Release allocated arguments.
+ void releaseMemory();
+
public:
InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
- ~InputArgList();
+ InputArgList(InputArgList &&RHS)
+ : ArgList(std::move(RHS)), ArgStrings(std::move(RHS.ArgStrings)),
+ SynthesizedStrings(std::move(RHS.SynthesizedStrings)),
+ NumInputArgStrings(RHS.NumInputArgStrings) {}
+ InputArgList &operator=(InputArgList &&RHS) {
+ releaseMemory();
+ ArgList::operator=(std::move(RHS));
+ ArgStrings = std::move(RHS.ArgStrings);
+ SynthesizedStrings = std::move(RHS.SynthesizedStrings);
+ NumInputArgStrings = RHS.NumInputArgStrings;
+ return *this;
+ }
+ ~InputArgList() { releaseMemory(); }
- virtual const char *getArgString(unsigned Index) const {
+ const char *getArgString(unsigned Index) const override {
return ArgStrings[Index];
}
- virtual unsigned getNumInputArgStrings() const {
+ unsigned getNumInputArgStrings() const override {
return NumInputArgStrings;
}
unsigned MakeIndex(StringRef String0) const;
unsigned MakeIndex(StringRef String0, StringRef String1) const;
- virtual const char *MakeArgString(StringRef Str) const;
+ using ArgList::MakeArgString;
+ const char *MakeArgStringRef(StringRef Str) const override;
/// @}
};
/// DerivedArgList - An ordered collection of driver arguments,
/// whose storage may be in another argument list.
-class DerivedArgList : public ArgList {
+class DerivedArgList final : public ArgList {
const InputArgList &BaseArgs;
/// The list of arguments we synthesized.
- mutable arglist_type SynthesizedArgs;
+ mutable SmallVector<std::unique_ptr<Arg>, 16> SynthesizedArgs;
public:
/// Construct a new derived arg list from \p BaseArgs.
DerivedArgList(const InputArgList &BaseArgs);
- ~DerivedArgList();
- virtual const char *getArgString(unsigned Index) const {
+ const char *getArgString(unsigned Index) const override {
return BaseArgs.getArgString(Index);
}
- virtual unsigned getNumInputArgStrings() const {
+ unsigned getNumInputArgStrings() const override {
return BaseArgs.getNumInputArgStrings();
}
/// AddSynthesizedArg - Add a argument to the list of synthesized arguments
/// (to be freed).
- void AddSynthesizedArg(Arg *A) {
- SynthesizedArgs.push_back(A);
- }
+ void AddSynthesizedArg(Arg *A);
- virtual const char *MakeArgString(StringRef Str) const;
+ using ArgList::MakeArgString;
+ const char *MakeArgStringRef(StringRef Str) const override;
/// AddFlagArg - Construct a new FlagArg for the given option \p Id and
/// append it to the argument list.