From: Daniel Dunbar Date: Wed, 25 Nov 2009 11:33:30 +0000 (+0000) Subject: Add an arg_iterator, for iterating over a subset of arguments in an ArgList. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3b84f5bab9f134741cf4d3c80086009519b6d968;p=clang Add an arg_iterator, for iterating over a subset of arguments in an ArgList. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89860 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h index 5263108d1a..beb92e7209 100644 --- a/include/clang/Driver/ArgList.h +++ b/include/clang/Driver/ArgList.h @@ -25,8 +25,66 @@ namespace llvm { namespace clang { namespace driver { class Arg; + class ArgList; class Option; + /// arg_iterator - Iterates through arguments stored inside an ArgList. + class arg_iterator { + /// The current argument. + llvm::SmallVectorImpl::const_iterator Current; + + /// The argument list we are iterating over. + const ArgList &Args; + + /// Optional filters on the arguments which will be match. Most clients + /// should never want to iterate over arguments without filters, so we won't + /// bother to factor this into two separate iterator implementations. + // + // FIXME: Make efficient; the idea is to provide efficient iteration over + // all arguments which match a particular id and then just provide an + // iterator combinator which takes multiple iterators which can be + // efficiently compared and returns them in order. + OptSpecifier Id0, Id1, Id2; + + void SkipToNextArg(); + + public: + typedef const Arg* value_type; + typedef const Arg* reference; + typedef const Arg* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + arg_iterator(llvm::SmallVectorImpl::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(); + } + + reference operator*() const { return *Current; } + pointer operator->() const { return *Current; } + + arg_iterator &operator++() { + ++Current; + SkipToNextArg(); + return *this; + } + + arg_iterator operator++(int) { + arg_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(arg_iterator LHS, arg_iterator RHS) { + return LHS.Current == RHS.Current; + } + friend bool operator!=(arg_iterator LHS, arg_iterator RHS) { + return !(LHS == RHS); + } + }; + /// ArgList - Ordered collection of driver arguments. /// /// The ArgList class manages a list of Arg instances as well as @@ -62,6 +120,10 @@ namespace driver { unsigned size() const { return Args.size(); } + /// @} + /// @name Arg Iteration + /// @{ + iterator begin() { return Args.begin(); } iterator end() { return Args.end(); } @@ -74,6 +136,18 @@ namespace driver { const_reverse_iterator rbegin() const { return Args.rbegin(); } const_reverse_iterator rend() const { return Args.rend(); } + arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U, + OptSpecifier Id2 = 0U) const { + return arg_iterator(Args.begin(), *this, Id0, Id1, Id2); + } + arg_iterator filtered_end() const { + return arg_iterator(Args.end(), *this); + } + + /// @} + /// @name Arg Access + /// @{ + /// hasArg - Does the arg list contain any option matching \arg Id. /// /// \arg Claim Whether the argument should be claimed, if it exists. @@ -115,17 +189,13 @@ namespace driver { void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const; /// AddAllArgs - Render all arguments matching the given ids. - void AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const; void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, - OptSpecifier Id1) const; - void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, OptSpecifier Id1, - OptSpecifier Id2) const; + OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; /// AddAllArgValues - Render the argument values of all arguments /// matching the given ids. - void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0) const; void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, - OptSpecifier Id1) const; + OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; /// AddAllArgsTranslated - Render all the arguments matching the /// given ids, but forced to separate args and using the provided diff --git a/include/clang/Driver/OptSpecifier.h b/include/clang/Driver/OptSpecifier.h index c38b36c2f7..bb1cd1740b 100644 --- a/include/clang/Driver/OptSpecifier.h +++ b/include/clang/Driver/OptSpecifier.h @@ -22,9 +22,12 @@ namespace driver { explicit OptSpecifier(bool); // DO NOT IMPLEMENT public: + OptSpecifier() : ID(0) {} /*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {} /*implicit*/ OptSpecifier(const Option *Opt); + bool isValid() const { return ID != 0; } + unsigned getID() const { return ID; } bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); } diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp index ea75c34ea5..8a57d14932 100644 --- a/lib/Driver/ArgList.cpp +++ b/lib/Driver/ArgList.cpp @@ -17,6 +17,23 @@ using namespace clang::driver; +void arg_iterator::SkipToNextArg() { + for (; Current != Args.end(); ++Current) { + // Done if there are no filters. + if (!Id0.isValid()) + break; + + // Otherwise require a match. + const Option &O = (*Current)->getOption(); + if (O.matches(Id0) || + (Id1.isValid() && O.matches(Id1)) || + (Id2.isValid() && O.matches(Id2))) + break; + } +} + +// + ArgList::ArgList(arglist_type &_Args) : Args(_Args) { } @@ -98,95 +115,46 @@ void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const { } } -void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const { - // FIXME: Make fast. - for (const_iterator it = begin(), ie = end(); it != ie; ++it) { - const Arg *A = *it; - if (A->getOption().matches(Id0)) { - A->claim(); - A->render(*this, Output); - } - } -} - -void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0, - OptSpecifier Id1) const { - // FIXME: Make fast. - for (const_iterator it = begin(), ie = end(); it != ie; ++it) { - const Arg *A = *it; - if (A->getOption().matches(Id0) || A->getOption().matches(Id1)) { - A->claim(); - A->render(*this, Output); - } - } -} - void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const { - // FIXME: Make fast. - for (const_iterator it = begin(), ie = end(); it != ie; ++it) { - const Arg *A = *it; - if (A->getOption().matches(Id0) || A->getOption().matches(Id1) || - A->getOption().matches(Id2)) { - A->claim(); - A->render(*this, Output); - } - } -} - -void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0) const { - // FIXME: Make fast. - for (const_iterator it = begin(), ie = end(); it != ie; ++it) { - const Arg *A = *it; - if (A->getOption().matches(Id0)) { - A->claim(); - for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) - Output.push_back(A->getValue(*this, i)); - } + for (arg_iterator it = filtered_begin(Id0, Id1, Id2), + ie = filtered_end(); it != ie; ++it) { + it->claim(); + it->render(*this, Output); } } void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, - OptSpecifier Id1) const { - // FIXME: Make fast. - for (const_iterator it = begin(), ie = end(); it != ie; ++it) { - const Arg *A = *it; - if (A->getOption().matches(Id0) || A->getOption().matches(Id1)) { - A->claim(); - for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) - Output.push_back(A->getValue(*this, i)); - } + OptSpecifier Id1, OptSpecifier Id2) const { + for (arg_iterator it = filtered_begin(Id0, Id1, Id2), + ie = filtered_end(); it != ie; ++it) { + it->claim(); + for (unsigned i = 0, e = it->getNumValues(); i != e; ++i) + Output.push_back(it->getValue(*this, i)); } } void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, const char *Translation, bool Joined) const { - // FIXME: Make fast. - for (const_iterator it = begin(), ie = end(); it != ie; ++it) { - const Arg *A = *it; - if (A->getOption().matches(Id0)) { - A->claim(); - - if (Joined) { - std::string Value = Translation; - Value += A->getValue(*this, 0); - Output.push_back(MakeArgString(Value.c_str())); - } else { - Output.push_back(Translation); - Output.push_back(A->getValue(*this, 0)); - } + for (arg_iterator it = filtered_begin(Id0), + ie = filtered_end(); it != ie; ++it) { + it->claim(); + + if (Joined) { + Output.push_back(MakeArgString(llvm::StringRef(Translation) + + it->getValue(*this, 0))); + } else { + Output.push_back(Translation); + Output.push_back(it->getValue(*this, 0)); } } } void ArgList::ClaimAllArgs(OptSpecifier Id0) const { - // FIXME: Make fast. - for (const_iterator it = begin(), ie = end(); it != ie; ++it) { - const Arg *A = *it; - if (A->getOption().matches(Id0)) - A->claim(); - } + for (arg_iterator it = filtered_begin(Id0), + ie = filtered_end(); it != ie; ++it) + it->claim(); } const char *ArgList::MakeArgString(const llvm::Twine &T) const {