Index: include/llvm/Option/ArgList.h =================================================================== --- include/llvm/Option/ArgList.h +++ include/llvm/Option/ArgList.h @@ -45,7 +45,7 @@ // efficiently compared and returns them in order. OptSpecifier Id0, Id1, Id2; - void SkipToNextArg(); + void skipToArg(bool Forward); public: typedef Arg * const * value_type; @@ -58,7 +58,7 @@ OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) : Current(it), Args(Args), Id0(Id0), Id1(Id1), Id2(Id2) { - SkipToNextArg(); + skipToArg(true /*Forward*/); } operator const Arg*() { return *Current; } @@ -67,14 +67,26 @@ arg_iterator &operator++() { ++Current; - SkipToNextArg(); + skipToArg(true /*Forward*/); return *this; } arg_iterator operator++(int) { - arg_iterator tmp(*this); + arg_iterator Ret(*this); ++(*this); - return tmp; + return Ret; + } + + arg_iterator &operator--() { + --Current; + skipToArg(false /*Forward*/); + return *this; + } + + arg_iterator operator--(int) { + arg_iterator Ret(*this); + --(*this); + return Ret; } friend bool operator==(arg_iterator LHS, arg_iterator RHS) { @@ -155,14 +167,16 @@ OptSpecifier Id2 = 0U) const { return arg_iterator(Args.begin(), *this, Id0, Id1, Id2); } - arg_iterator filtered_end() const { - return arg_iterator(Args.end(), *this); + arg_iterator filtered_end(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U, + OptSpecifier Id2 = 0U) const { + return arg_iterator(Args.end(), *this, Id0, Id1, Id2); } iterator_range filtered(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const { - return make_range(filtered_begin(Id0, Id1, Id2), filtered_end()); + return make_range(filtered_begin(Id0, Id1, Id2), + filtered_end(Id0, Id1, Id2)); } /// @} Index: lib/Option/ArgList.cpp =================================================================== --- lib/Option/ArgList.cpp +++ lib/Option/ArgList.cpp @@ -19,18 +19,21 @@ using namespace llvm; using namespace llvm::opt; -void arg_iterator::SkipToNextArg() { - for (; Current != Args.end(); ++Current) { +void arg_iterator::skipToArg(bool Forward) { + auto End = Forward ? Args.end() : Args.begin(); + + while (Current != End) { // 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)) || + if (O.matches(Id0) || (Id1.isValid() && O.matches(Id1)) || (Id2.isValid() && O.matches(Id2))) break; + + Current += Forward ? 1 : -1; } } Index: unittests/Option/OptionParsingTest.cpp =================================================================== --- unittests/Option/OptionParsingTest.cpp +++ unittests/Option/OptionParsingTest.cpp @@ -105,6 +105,23 @@ ASSERT_EQ(2u, ASL.size()); EXPECT_EQ("-C", StringRef(ASL[0])); EXPECT_EQ("desu", StringRef(ASL[1])); + + // Test iterator operators. + arg_iterator CsIt = AL.filtered_begin(OPT_C); + arg_iterator CsOp1 = CsIt++; + EXPECT_EQ("desu", StringRef((*CsOp1)->getValue())); + EXPECT_EQ("bye", StringRef((*CsIt)->getValue())); + arg_iterator CsOp2 = CsIt--; + EXPECT_EQ("bye", StringRef((*CsOp2)->getValue())); + EXPECT_EQ("desu", StringRef((*CsIt)->getValue())); + arg_iterator CsOp3 = ++CsIt; + EXPECT_EQ("bye", StringRef((*CsOp3)->getValue())); + EXPECT_EQ("bye", StringRef((*CsIt)->getValue())); + arg_iterator CsOp4 = --CsIt; + EXPECT_EQ("desu", StringRef((*CsOp4)->getValue())); + EXPECT_EQ("desu", StringRef((*CsIt)->getValue())); + arg_iterator CsItEnd = AL.filtered_end(OPT_C); + EXPECT_EQ("bye", StringRef((*--CsItEnd)->getValue())); } TEST(Option, ParseWithFlagExclusions) {