https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109732
--- Comment #9 from Martin Liška <marxin at gcc dot gnu.org> ---
I've got a C++ reduced test-case:
$ cat x.ii
template <typename> struct is_same;
template <bool, typename _Tp> using enable_if_t = _Tp;
template <typename _Iterator> struct reverse_iterator {
_Iterator current;
typedef _Iterator iterator_type;
reverse_iterator(iterator_type __x) : current(__x) {}
iterator_type base() { return current; }
};
template <typename _Iterator>
bool operator==(reverse_iterator<_Iterator> __x,
reverse_iterator<_Iterator> __y) {
return __x.base() == __y.base();
}
struct __normal_iterator {
int _M_current;
};
template <typename> struct __new_allocator;
template <typename> struct allocator_traits;
template <typename _Tp> struct allocator_traits<__new_allocator<_Tp>> {
using const_pointer = _Tp *;
};
template <typename> struct vector {
typedef __normal_iterator iterator;
};
namespace {
enum value_t { null, object, array, string };
template <template <typename, typename...> class = vector,
template <typename> class = __new_allocator>
class basic_json;
struct external_constructor {
template <
typename BasicJsonType, typename CompatibleStringType,
enable_if_t<is_same<typename BasicJsonType::string_t>::value, int> = 0>
static void construct(BasicJsonType &j, CompatibleStringType) {
j.m_type = string;
}
} to_json_s;
void to_json(basic_json<> &j) { external_constructor::construct(j, to_json_s);
}
long begin_value;
long end_value = 1;
struct primitive_iterator_t {
long m_it;
void set_begin() { m_it = begin_value; }
void set_end() { m_it = end_value; }
friend bool operator==(primitive_iterator_t, primitive_iterator_t rhs) {
return rhs.m_it;
}
};
template <typename BasicJsonType> struct internal_iterator {
typename BasicJsonType::array_t::iterator array_iterator;
primitive_iterator_t primitive_iterator;
};
template <typename BasicJsonType> struct iter_impl {
using array_t = typename BasicJsonType::array_t;
typedef typename BasicJsonType::const_pointer pointer;
iter_impl(pointer object) : m_object(object) {
switch (m_object->m_type)
case ::object:
case array:
m_it.array_iterator = typename array_t::iterator();
}
void set_begin() {
switch (m_object->m_type) {
case object:
case array:
break;
case null:
m_it.primitive_iterator.set_end();
break;
default:
m_it.primitive_iterator.set_begin();
}
}
template <typename IterImpl> bool operator==(IterImpl other) {
return m_it.primitive_iterator == other.m_it.primitive_iterator;
}
pointer m_object;
internal_iterator<BasicJsonType> m_it;
};
template <typename Base> struct json_reverse_iterator : reverse_iterator<Base>
{
json_reverse_iterator(Base it) : reverse_iterator<Base>(it) {}
};
template <template <typename, typename...> class ArrayType,
template <typename> class AllocatorType>
struct basic_json {
using const_pointer =
typename allocator_traits<AllocatorType<basic_json>>::const_pointer;
using const_iterator = iter_impl<basic_json>;
using const_reverse_iterator = json_reverse_iterator<const_iterator>;
using array_t = ArrayType<basic_json>;
template <typename CompatibleType> basic_json(CompatibleType) {
to_json(*this);
}
const_iterator cbegin() {
const_iterator result(this);
result.set_begin();
return result;
}
const_iterator cend() {
const_iterator result(this);
return result;
}
const_reverse_iterator crbegin() { return cend(); }
const_reverse_iterator crend() { return cbegin(); }
value_t m_type;
};
} // namespace
int seen_failures;
__attribute__((noinline)) void sne(basic_json<>::const_reverse_iterator lhs,
basic_json<>::const_reverse_iterator rhs) {
bool res = !(lhs == rhs);
if (!res)
seen_failures++;
}
basic_json main_js = "";
int
main() {
basic_json js_const(main_js);
basic_json<>::const_reverse_iterator sit = js_const.crbegin(),
__trans_tmp_1 = js_const.crend();
sne(sit, __trans_tmp_1);
return seen_failures;
}