Skip to content

Commit dd1a928

Browse files
committed
Correctly instantiate iterator_adaptor_base when defining pointer_iterator
The definition of `pointer_iterator` omits what should be a `iterator_traits::<>::iterator_category` parameter from `iterator_adaptor_base`. As a result, iterators based on `pointer_iterator` always have defaulted value types and the wrong iterator category. The definition of `pointee_iterator` just a few lines above does this correctly. This resolves [[ https://bugs.llvm.org/show_bug.cgi?id=39617 | bug 39617 ]]. Patch by Dylan MacKenzie! Reviewers: dblaikie Differential Revision: https://reviews.llvm.org/D54377 llvm-svn: 346833
1 parent 2bcc951 commit dd1a928

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

llvm/include/llvm/ADT/iterator.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,10 @@ make_pointee_range(RangeT &&Range) {
309309
template <typename WrappedIteratorT,
310310
typename T = decltype(&*std::declval<WrappedIteratorT>())>
311311
class pointer_iterator
312-
: public iterator_adaptor_base<pointer_iterator<WrappedIteratorT, T>,
313-
WrappedIteratorT, T> {
312+
: public iterator_adaptor_base<
313+
pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT,
314+
typename std::iterator_traits<WrappedIteratorT>::iterator_category,
315+
T> {
314316
mutable T Ptr;
315317

316318
public:

llvm/unittests/ADT/IteratorTest.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10+
#include "llvm/ADT/ilist.h"
1011
#include "llvm/ADT/iterator.h"
1112
#include "llvm/ADT/ArrayRef.h"
1213
#include "llvm/ADT/STLExtras.h"
@@ -35,6 +36,34 @@ static_assert(std::is_same<typename AdaptedIter::pointer, Shadow<2>>::value,
3536
static_assert(std::is_same<typename AdaptedIter::reference, Shadow<3>>::value,
3637
"");
3738

39+
// Ensure that pointe{e,r}_iterator adaptors correctly forward the category of
40+
// the underlying iterator.
41+
42+
using RandomAccessIter = SmallVectorImpl<int*>::iterator;
43+
using BidiIter = ilist<int*>::iterator;
44+
45+
template<class T>
46+
using pointee_iterator_defaulted = pointee_iterator<T>;
47+
template<class T>
48+
using pointer_iterator_defaulted = pointer_iterator<T>;
49+
50+
// Ensures that an iterator and its adaptation have the same iterator_category.
51+
template<template<typename> class A, typename It>
52+
using IsAdaptedIterCategorySame =
53+
std::is_same<typename std::iterator_traits<It>::iterator_category,
54+
typename std::iterator_traits<A<It>>::iterator_category>;
55+
56+
// pointeE_iterator
57+
static_assert(IsAdaptedIterCategorySame<pointee_iterator_defaulted,
58+
RandomAccessIter>::value, "");
59+
static_assert(IsAdaptedIterCategorySame<pointee_iterator_defaulted,
60+
BidiIter>::value, "");
61+
// pointeR_iterator
62+
static_assert(IsAdaptedIterCategorySame<pointer_iterator_defaulted,
63+
RandomAccessIter>::value, "");
64+
static_assert(IsAdaptedIterCategorySame<pointer_iterator_defaulted,
65+
BidiIter>::value, "");
66+
3867
TEST(PointeeIteratorTest, Basic) {
3968
int arr[4] = {1, 2, 3, 4};
4069
SmallVector<int *, 4> V;

0 commit comments

Comments
 (0)