This is an archive of the discontinued LLVM Phabricator instance.

[ADT] Make iterable SmallVector template overrides more specific
ClosedPublic

Authored by fjricci on Jun 5 2017, 4:21 PM.

Details

Summary

This prevents the iterator overrides from being selected in
the case where non-iterator types are used as arguments, which
is of particular importance in cases where other overrides with
identical types exist.

Diff Detail

Repository
rL LLVM

Event Timeline

fjricci created this revision.Jun 5 2017, 4:21 PM
efriedma added inline comments.
include/llvm/ADT/SmallVector.h
429 ↗(On Diff #101474)

This change doesn't do anything; typename and class are equivalent in this context. From your description, maybe you want something using std::enable_if?

fjricci updated this revision to Diff 101596.Jun 6 2017, 11:36 AM
fjricci retitled this revision from [ADT] Enforce class type for overridden SmallVector assign to [ADT] Ensure that correct overrides for SmallVector assign are selected.
fjricci removed a subscriber: efriedma.

Enforce that template arguments are not integral types

The only possible conflicting override takes a size_type, and enforcing that the
type is not an integral type is much more straightforward than enforcing that it is
either an iterator, const iterator, pointer, or const pointer.

Accidentally removed a subscriber, re-adding

fjricci updated this revision to Diff 101813.Jun 7 2017, 1:56 PM
fjricci retitled this revision from [ADT] Ensure that correct overrides for SmallVector assign are selected to [ADT] Make iterable SmallVector template overrides more specific.
fjricci edited the summary of this revision. (Show Details)

Add unit test and migrate to iterator SFINAE checks

fjricci updated this revision to Diff 101815.Jun 7 2017, 2:31 PM

Add test cases for all 3 specialized methods

fjricci updated this revision to Diff 101943.Jun 8 2017, 10:53 AM

Use input_iterator_tag

dblaikie edited edge metadata.Jun 8 2017, 11:04 AM

I think this is just about right - but the current SFINAE is only an exact match, so it wouldn't work for something that's, say, a RandomAccessIterator.

I believe you want to use std::is_convertible_to, rather than std::is_same (& maybe add coverage/a test case for a non-forward (for example, a random access - such as pointers to the begin/end of an array) for this).

I'm guessing using is_same should've broken some existing code in LLVM - I'm surprised it didn't break the unit test? So maybe I'm misunderstantding something about how this is working.

(I really appreciate your patience as we go around on this - sorry it's taken a few iterations)

The llvm test suite passes with this change, although I haven't verified clang's does yet. I'll add a test for a random access iterator, and update the enable_if if it doesn't work correctly.

assign(&arr[0], &arr[2]) fails both with is_same and is_convertible. Is that an acceptable usage of assign (and what you meant by random access iterator)? There's already a test case for assign(std::begin(arr), std::end(arr)), and that works fine with is_same.

It looks like random_access_iterator_tag inherits from input_iterator_tag (http://en.cppreference.com/w/cpp/iterator/iterator_tags), so maybe that's why is_same works?

fjricci updated this revision to Diff 102038.Jun 9 2017, 8:40 AM

Use is_convertible and ::type

dblaikie accepted this revision.Jun 9 2017, 10:28 AM

Please add a test case using a non-forward iterator to demonstrate that the traits checking is working as intended.

I think something like this, maybe:

TYPED_TEST(SmallVectorTest, InsertRepeatedNonForwardIterator) {
  struct output_iterator {
    typedef std::output_iterator_tag iterator_category;
    typedef int        value_type;
    typedef int   difference_type;
    typedef value_type*        pointer;
    typedef value_type&        reference;
    // In theory other operations would be needed here, but they shouldn't be used in this test
    operator int() { return 2; }
  };
  
  ...
  append(output_iterator(), output_iterator())
  check that the vector describes the sequence {2, 2}
}

I suppose in theory this should be tested for all 4 operations you're updating here - if there's a tidy way to do that, great, but otherwise I'd probably just test one of them.

Also there seem to be 3 test cases but 4 code changes. The ctor change isn't tested at all - could you test that?

This revision is now accepted and ready to land.Jun 9 2017, 10:28 AM
fjricci updated this revision to Diff 102061.Jun 9 2017, 11:40 AM

Add more testing

dblaikie accepted this revision.Jun 9 2017, 11:45 AM

Looks great - thanks again for all your patience/help!

This revision was automatically updated to reflect the committed changes.