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; }