https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122903
Bug ID: 122903
Summary: [16 Regression] gjs-1.86.0 fails to build since
r16-4100-gaaeca77a79a9a8
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: slyfox at gcc dot gnu.org
Target Milestone: ---
I'm not sure if it's a regression or an intentional change. But since
r16-4100-gaaeca77a79a9a8 (bisected) `gjs-1.86.0` started failing to build.
I proposed the upstream fix as:
https://gitlab.gnome.org/GNOME/gjs/-/merge_requests/1046
But I'm not sure if the API change is intentional and whether iterator `gjs`
implements is correct. Filing the bug just in case.
Here is the extracted reproducer from `gjs`:
// $ cat a.cc
#include <algorithm>
#include <iterator>
// gjs calls it OwnedInfo
class T {
T() = delete;
public:
explicit T(const T&);
T(T && o);
T& operator=(const T&);
T& operator=(T&&);
};
// gjs calls it `class InfoIterator`
struct I {
bool operator==(const class I &) const;
bool operator!=(const class I &) const;
I& operator++();
T operator*(); // Note, not the `T&` reference!
typedef std::input_iterator_tag iterator_category;
typedef int difference_type;
typedef T value_type;
typedef value_type* pointer;
typedef value_type& reference;
};
bool struct_is_simple(I b, I e) {
return std::all_of(b, e, [](T) { return false; });
}
gcc-14, work as is:
$ g++-14 -c a.cc -std=c++11
# ok
gcc-master fails:
$ g++ -c a.cc -std=c++11
In file included from
/<<NIX>>/gcc-16.0.0.99999999/include/c++/16.0.0.99999999/bits/stl_algobase.h:71,
from
/<<NIX>>/gcc-16.0.0.99999999/include/c++/16.0.0.99999999/algorithm:62,
from a.cc:1:
/<<NIX>>/gcc-16.0.0.99999999/include/c++/16.0.0.99999999/bits/predefined_ops.h:
In instantiation of 'bool
__gnu_cxx::__ops::_Unary_negate<_Func>::operator()(_Tp&&) [with _Tp = T; _Func
= struct_is_simple(I, I)::<lambda(T)>]':
required from '_Iterator std::__find_if(_Iterator, _Iterator, _Predicate) [with
_Iterator = I; _Predicate = __gnu_cxx::__ops::_Unary_negate<struct_is_simple(I,
I)::<lambda(T)> >]'
/<<NIX>>/gcc-16.0.0.99999999/include/c++/16.0.0.99999999/bits/stl_algobase.h:2103:42:
2103 | while (__first != __last && !__pred(*__first))
| ~~~~~~^~~~~~~~~~
required from '_InputIterator std::__find_if_not(_InputIterator,
_InputIterator, _Predicate) [with _InputIterator = I; _Predicate =
struct_is_simple(I, I)::<lambda(T)>]'
/<<NIX>>/gcc-16.0.0.99999999/include/c++/16.0.0.99999999/bits/stl_algo.h:115:28:
115 | return std::__find_if(__first, __last,
| ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
116 | __gnu_cxx::__ops::not1(__pred));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
required from '_IIter std::find_if_not(_IIter, _IIter, _Predicate) [with _IIter
= I; _Predicate = struct_is_simple(I, I)::<lambda(T)>]'
/<<NIX>>/gcc-16.0.0.99999999/include/c++/16.0.0.99999999/bits/stl_algo.h:473:32:
473 | return std::__find_if_not(__first, __last, __pred);
| ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
required from 'bool std::all_of(_IIter, _IIter, _Predicate) [with _IIter = I;
_Predicate = struct_is_simple(I, I)::<lambda(T)>]'
/<<NIX>>/gcc-16.0.0.99999999/include/c++/16.0.0.99999999/bits/stl_algo.h:413:40:
413 | { return __last == std::find_if_not(__first, __last, __pred); }
| ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
required from here
a.cc:31:23:
31 | return std::all_of(b, e, [](T) { return false; });
| ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/<<NIX>>/gcc-16.0.0.99999999/include/c++/16.0.0.99999999/bits/predefined_ops.h:105:47:
error: cannot bind rvalue reference of type 'T&&' to lvalue of type 'T'
105 | operator()(_Tp&& __arg) { return !_M_f(__arg); }
| ~~~~^~~~~~~
a.cc:9:10: note: initializing argument 1 of 'T::T(T&&)'
9 | T(T && o);
| ~~~~~^
a.cc:31:30: note: initializing argument 1 of 'struct_is_simple(I,
I)::<lambda(T)>'
31 | return std::all_of(b, e, [](T) { return false; });
| ^
Note that dereference iterator returns a value, not a reference: `T
operator*(); // Note, not the `T&` reference!`. If I change it to `T
operator*();` then both `gcc-14` and `gcc-master` start matching behaviour.
A few questions:
1. Is it expected that `gcc-14` / `gcc-master` differ in handling this code?
2. Is `T operator*();` a reasonable iterator implementaiton?
Thanks!