This is an archive of the discontinued LLVM Phabricator instance.

Improve StringMap iterator support.
ClosedPublic

Authored by zturner on Mar 20 2017, 10:47 PM.

Details

Summary

Make the two StringMap iterators support iterator_facade_base. This fixes some usage scenarios when passing begin and end to various STL algorithms. After doing that, it's easy to make a StringMapKeysIterator that only iterates keys, so I've done that as well.

Diff Detail

Repository
rL LLVM

Event Timeline

zturner created this revision.Mar 20 2017, 10:47 PM
dblaikie edited edge metadata.Mar 21 2017, 8:03 AM

Seems weird to have 'keys' on a StringSet, perhaps? (& to test StringSet in the StringMap unit test - as much as I realize the two types are very closely related)

Also, I'm wondering if keys() is necessary even on StringMap - I'd have thought a general-purpose "iterator of the first element of a pair" would suffice, but then remembered that StringMaps are special and their values are not pair<key, value> but have special accessors for the key, etc. So perhaps a lambda-driven iterator adapter... at which point, yeah, I can understand the utility of having that wrapped up in a reusable form.

llvm/include/llvm/ADT/StringExtras.h
255 ↗(On Diff #92433)

most of the other "iterator pair or range" algorithms use the same name for both (eg: all the llvm::any/all/none_of clones that take a range use the same name) - maybe use the same name here too ('join' rather than 'join_range') unless that causes some ambiguities?

Also - this seems like an unrelated change for this patch (& arguably could use test coverage if it is going to be committed). Guess maybe it slipped into this change.

llvm/include/llvm/ADT/StringMap.h
474 ↗(On Diff #92433)

Generally it's advised that any op overload that can be a non-member should be, to allow equal implicit conversions on both sides. (it can still be a friend, though:

friend bool operator==(LHS, RHS) { return LHS.Ptr == RHS.Ptr; }
533 ↗(On Diff #92433)

op* that returns by value - does that cause problems for op->? I forget...

llvm/unittests/Support/StringMap.cpp
38 ↗(On Diff #92433)

In retrospect, maybe this function should be called To(Small)Vector? (Since there's no standard library function it's trying to emulate, etc - and it actually produces a SmallVector, not a std::vector, so the name is a bit vague/misleading (& makes the int non-type template parameter unclear/confusing))

zturner added inline comments.Mar 21 2017, 8:13 AM
llvm/include/llvm/ADT/StringExtras.h
255 ↗(On Diff #92433)

Yea I almost called it join, but then saw that we have join and join_items so join_range seemed to fit nicely. That said, join_items was introduced because of an ambiguity with join, but join_range won't have that ambiguity, so we could still call it join.

llvm/include/llvm/ADT/StringMap.h
533 ↗(On Diff #92433)

Should be fine, the StringRef should live until the end of the sequence point.

zturner updated this revision to Diff 92507.Mar 21 2017, 10:13 AM
  1. Fixed issue with returning by value from operator*.
  2. Moved the test from Support to ADT, since there was already an existing StringMapTest class there that I hadn't noticed.
  3. Removed the join changes that had snuck in. I'll commit those separately.
dblaikie accepted this revision.Mar 21 2017, 10:25 AM

Some optional bits/pieces. (also - could include test coverage for op->. Or perhaps better/alternatively: put a static_assert in iterator_adapter_base to ensure that the return type of op* is a reference type?)

llvm/unittests/ADT/StringMapTest.cpp
287–300 ↗(On Diff #92507)

Not sure this test is necessary (I mean, depending on your perspective) - since it's testing the same API in StringMap that's inherited by StringSet - there's no new/interesting code under test here, compared to the previous test.

(should StringSet's iterators actually be key iterators, rather than a 'keys()' operation on a set, which doesn't quite make sense - it only has keys, no values, so why would there be two different ranges to iterate over?)

This revision is now accepted and ready to land.Mar 21 2017, 10:25 AM
zturner added inline comments.Mar 21 2017, 10:29 AM
llvm/unittests/ADT/StringMapTest.cpp
287–300 ↗(On Diff #92507)

Not sure this test is necessary (I mean, depending on your perspective) - since it's testing the same API in StringMap that's inherited by StringSet - there's no new/interesting code under test here, compared to the previous test.

True, but the same could be set for join_range vs join in the other patch. It doesn't matter to me either way though.

should StringSet's iterators actually be key iterators, rather than a 'keys()' operation on a set, which doesn't quite make sense - it only has keys, no values, so why would there be two different ranges to iterate over

I could rename the function in StringSet by bringing keys() into protected scope with a using declaration, then make a function in StringSet called values() which simply returns the result of keys(). Thoughts?

This revision was automatically updated to reflect the committed changes.