https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94696

            Bug ID: 94696
           Summary: std::search with a parallel policy calls predicate
                    with wrong argument types
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: schlong at cock dot li
  Target Milestone: ---

Created attachment 48325
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48325&action=edit
search with parallel execution policy

When `std::search` is called with a parallel execution policy
(`std::execution::par`, `std::execution::par_unseq`, `std::execution::unseq`)
and a binary predicate as the compare function, it tries to invoke the
predicate with wrong argument types.

```
// snippet is also attached as a file to the bug report
#include <algorithm>
#include <execution>

struct A{};
struct B{};

bool fn(A, B)
{
  return true;
}

int main()
{
  A a[1]{};
  B b[1]{};

  std::search(std::execution::par,
    a, a + 1,
    b, b + 1,
    fn);
}
```

Compile with
```
g++ -std=c++20
```
or c++2a if using an older version of gcc (Error also occurs in older versions
of gcc).

gcc -v
```
Target: x86_64-linux-gnu

Configured with: ../gcc-trunk-20200421/configure
--prefix=/opt/compiler-explorer/gcc-build/staging --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=x86_64-linux-gnu --disable-bootstrap
--enable-multiarch --with-abi=m64 --with-multilib-list=m32,m64,mx32
--enable-multilib --enable-clocale=gnu --enable-languages=c,c++,fortran,ada,d
--enable-ld=yes --enable-gold=yes --enable-libstdcxx-debug
--enable-libstdcxx-time=yes --enable-linker-build-id --enable-lto
--enable-plugins --enable-threads=posix
--with-pkgversion=Compiler-Explorer-Build

Thread model: posix

Supported LTO compression algorithms: zlib

gcc version 10.0.1 20200420 (experimental) (Compiler-Explorer-Build)
```

Output
```
In file included from
/opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/algorithm:61,

                 from <source>:2:

/opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/bits/stl_algobase.h:
In instantiation of 'constexpr bool std::equal(_IIter1, _IIter1, _IIter2,
_BinaryPredicate) [with _IIter1 = B*; _IIter2 = A*; _BinaryPredicate = bool
(*)(A, B)]':

/opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/pstl/algorithm_impl.h:449:22:
  required from 'bool __pstl::__internal::__brick_equal(_ForwardIterator1,
_ForwardIterator1, _ForwardIterator2, _BinaryPredicate, std::false_type) [with
_ForwardIterator1 = B*; _ForwardIterator2 = A*; _BinaryPredicate = bool (*)(A,
B); std::false_type = std::integral_constant<bool, false>]'

/opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/pstl/algorithm_impl.h:571:38:
  required from '_RandomAccessIterator1
__pstl::__internal::__find_subrange(_RandomAccessIterator1,
_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
_RandomAccessIterator2, _BinaryPredicate, bool, _IsVector) [with
_RandomAccessIterator1 = A*; _RandomAccessIterator2 = B*; _BinaryPredicate =
bool (*)(A, B); _IsVector = std::integral_constant<bool, false>]'

/opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/pstl/algorithm_impl.h:780:55:
  required from '_ForwardIterator1
__pstl::__internal::__pattern_search(_ExecutionPolicy&&, _ForwardIterator1,
_ForwardIterator1, _ForwardIterator2, _ForwardIterator2, _BinaryPredicate,
_IsVector, std::true_type) [with _ExecutionPolicy = const
__pstl::execution::v1::parallel_policy&; _ForwardIterator1 = A*;
_ForwardIterator2 = B*; _BinaryPredicate = bool (*)(A, B); _IsVector =
std::integral_constant<bool, false>; std::true_type =
std::integral_constant<bool, true>]'

/opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/pstl/glue_algorithm_impl.h:214:40:
  required from
'__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy,
_ForwardIterator> std::search(_ExecutionPolicy&&, _ForwardIterator1,
_ForwardIterator1, _ForwardIterator2, _ForwardIterator2, _BinaryPredicate)
[with _ExecutionPolicy = const __pstl::execution::v1::parallel_policy&;
_ForwardIterator1 = A*; _ForwardIterator2 = B*; _BinaryPredicate = bool (*)(A,
B); __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy,
_ForwardIterator> = A*]'

<source>:21:7:   required from here

/opt/compiler-explorer/gcc-trunk-20200421/include/c++/10.0.1/bits/stl_algobase.h:1437:25:
error: could not convert '* __first1' from 'B' to 'A'

 1437 |  if (!bool(__binary_pred(*__first1, *__first2)))

      |            ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~

      |                         |

      |                         B

Compiler returned: 1
```

The snippet compiles with MSVC v19.24.
The snippet compiles when not using an execution policy.
The snippet compiles when using `std::execution::seq`.

Reply via email to