Bug 291228 - C++ feature std::execution::unseq is missing in std::execution
Summary: C++ feature std::execution::unseq is missing in std::execution
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: misc (show other bugs)
Version: 15.0-CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-toolchain (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2025-11-26 07:27 UTC by Yuri Victorovich
Modified: 2025-11-27 04:02 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Yuri Victorovich freebsd_committer freebsd_triage 2025-11-26 07:27:06 UTC
The support table (https://en.cppreference.com/w/cpp/compiler_support.html) lists std::execution::unseq as implemented but it is missing in 15 STABLE.

The example from https://en.cppreference.com/w/cpp/algorithm/execution_policy_tag.html fails to compile with -DPARALLEL.
Comment 1 Mark Millard 2025-11-26 14:10:42 UTC
For reference:

# c++ -std=c++20 -DPARALLEL unseq_test.cc
unseq_test.cc:34:24: error: no member named 'seq' in namespace 'std::execution'
   34 |     measure(execution::seq, v);
      |             ~~~~~~~~~~~^
unseq_test.cc:35:24: error: no member named 'unseq' in namespace 'std::execution'
   35 |     measure(execution::unseq, v);
      |             ~~~~~~~~~~~^
unseq_test.cc:36:24: error: no member named 'par_unseq' in namespace 'std::execution'
   36 |     measure(execution::par_unseq, v);
      |             ~~~~~~~~~~~^
unseq_test.cc:37:24: error: no member named 'par' in namespace 'std::execution'
   37 |     measure(execution::par, v);
      |             ~~~~~~~~~~~^
4 errors generated.

The same happens on both, for example (note the 1500502 and 1600004):

# uname -apKU
FreeBSD 7950X3D-ZFS 16.0-CURRENT FreeBSD 16.0-CURRENT main-n281922-4872b48b175c GENERIC-NODEBUG amd64 amd64 1600004 1500502

# uname -apKU
FreeBSD aarch64-main-pbase 16.0-CURRENT FreeBSD 16.0-CURRENT main-n281922-4872b48b175c GENERIC-NODEBUG arm64 aarch64 1600004 1600004


I will note:

# c++ -std=c++20 -fexperimental-library -DPARALLEL unseq_test.cc
unseq_test.cc:34:13: error: call to deleted constructor of 'std::execution::sequenced_policy'
   34 |     measure(execution::seq, v);
      |             ^~~~~~~~~~~~~~
/usr/include/c++/v1/execution:52:3: note: 'sequenced_policy' has been explicitly marked deleted here
   52 |   sequenced_policy(const sequenced_policy&)            = delete;
      |   ^
unseq_test.cc:15:36: note: passing argument to parameter 'policy' here
   15 | void measure([[maybe_unused]] auto policy, std::vector<std::uint64_t> v)
      |                                    ^
unseq_test.cc:35:13: error: call to deleted constructor of 'std::execution::unsequenced_policy'
   35 |     measure(execution::unseq, v);
      |             ^~~~~~~~~~~~~~~~
/usr/include/c++/v1/execution:86:3: note: 'unsequenced_policy' has been explicitly marked deleted here
   86 |   unsequenced_policy(const unsequenced_policy&)            = delete;
      |   ^
unseq_test.cc:15:36: note: passing argument to parameter 'policy' here
   15 | void measure([[maybe_unused]] auto policy, std::vector<std::uint64_t> v)
      |                                    ^
unseq_test.cc:36:13: error: call to deleted constructor of 'std::execution::parallel_unsequenced_policy'
   36 |     measure(execution::par_unseq, v);
      |             ^~~~~~~~~~~~~~~~~~~~
/usr/include/c++/v1/execution:68:3: note: 'parallel_unsequenced_policy' has been explicitly marked deleted here
   68 |   parallel_unsequenced_policy(const parallel_unsequenced_policy&)            = delete;
      |   ^
unseq_test.cc:15:36: note: passing argument to parameter 'policy' here
   15 | void measure([[maybe_unused]] auto policy, std::vector<std::uint64_t> v)
      |                                    ^
unseq_test.cc:37:13: error: call to deleted constructor of 'std::execution::parallel_policy'
   37 |     measure(execution::par, v);
      |             ^~~~~~~~~~~~~~
/usr/include/c++/v1/execution:60:3: note: 'parallel_policy' has been explicitly marked deleted here
   60 |   parallel_policy(const parallel_policy&)            = delete;
      |   ^
unseq_test.cc:15:36: note: passing argument to parameter 'policy' here
   15 | void measure([[maybe_unused]] auto policy, std::vector<std::uint64_t> v)
      |                                    ^
4 errors generated.


I wonder if this is an upstream issue relative to llvm19's libc++ .

For reference:

# g++15 -std=c++20 -DPARALLEL -Wl,-rpath=/usr/local/lib/gcc15 unseq_test.cc

# ./a.out
341ms
341ms
339ms
339ms

But on aarch64 main 16:

# g++15 -std=c++20 -DPARALLEL unseq_test.cc

# ./a.out
ld-elf.so.1: /lib/libgcc_s.so.1: version GCC_4.5.0 required by /root/c_tests/a.out not found
Comment 2 Mark Millard 2025-11-27 02:57:43 UTC
The system llvm19 libc++ has . . .

contrib/llvm-project/libcxx/modules/std/execution.inc

with:

// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifdef _LIBCPP_ENABLE_EXPERIMENTAL
export namespace std {
  // [execpol.type], execution policy type trait
  using std::is_execution_policy;
  using std::is_execution_policy_v;
} // namespace std

export namespace std::execution {
  // [execpol.seq], sequenced execution policy
  using std::execution::sequenced_policy;

  // [execpol.par], parallel execution policy
  using std::execution::parallel_policy;

  // [execpol.parunseq], parallel and unsequenced execution policy
  using std::execution::parallel_unsequenced_policy;

  // [execpol.unseq], unsequenced execution policy
  using std::execution::unsequenced_policy;

  // [execpol.objects], execution policy objects
  using std::execution::par;
  using std::execution::par_unseq;
  using std::execution::seq;
  using std::execution::unseq;
} // namespace std::execution
#endif // _LIBCPP_ENABLE_EXPERIMENTAL

So your reference material that you based the submittal on
is just wrong as of llvm19 --unless it considers requiring
use of -fexperimental-library to enable that part of the
library as still being supported.

And, my earlier report shows it is not actually supported
even with -fexperimental-library specified.

It looks to be an upstream issue, not a FreeBSD one. This
was submitted to the wrong place.
Comment 3 Mark Millard 2025-11-27 03:55:03 UTC
(In reply to Mark Millard from comment #2)

That was for a modules context. Going the other
way . . .

contrib/llvm-project/libcxx/include/exception has:

#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17

_LIBCPP_BEGIN_NAMESPACE_STD

namespace execution {
struct sequenced_policy {
  _LIBCPP_HIDE_FROM_ABI constexpr explicit sequenced_policy(__disable_user_instantiations_tag) {}
  sequenced_policy(const sequenced_policy&)            = delete;
  sequenced_policy& operator=(const sequenced_policy&) = delete;
};

inline constexpr sequenced_policy seq{__disable_user_instantiations_tag{}};

. . .

(In reply to Mark Millard from comment #2)

That was for a modules context. Going the other
way . . .

contrib/llvm-project/libcxx/include/exception has:

#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17

_LIBCPP_BEGIN_NAMESPACE_STD

namespace execution {
struct sequenced_policy {
  _LIBCPP_HIDE_FROM_ABI constexpr explicit sequenced_policy(__disable_user_instantiations_tag) {}
  sequenced_policy(const sequenced_policy&)            = delete;
  sequenced_policy& operator=(const sequenced_policy&) = delete;
};

inline constexpr sequenced_policy seq{__disable_user_instantiations_tag{}};

. . .

#  if _LIBCPP_STD_VER >= 20

struct unsequenced_policy {
  _LIBCPP_HIDE_FROM_ABI constexpr explicit unsequenced_policy(__disable_user_instantiations_tag) {}
  unsequenced_policy(const unsequenced_policy&)            = delete;
  unsequenced_policy& operator=(const unsequenced_policy&) = delete;
};

inline constexpr unsequenced_policy unseq{__disable_user_instantiations_tag{}};

#  endif // _LIBCPP_STD_VER >= 20

} // namespace execution
. . .

where contrib/llvm-project/libcxx/include/__config has:

// Incomplete features get their own specific disabling flags. This makes it
// easier to grep for target specific flags once the feature is complete.
#  if !defined(_LIBCPP_ENABLE_EXPERIMENTAL) && !defined(_LIBCPP_BUILDING_LIBRARY)
#    define _LIBCPP_HAS_NO_INCOMPLETE_PSTL
#    define _LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN
#    define _LIBCPP_HAS_NO_EXPERIMENTAL_TZDB
#    define _LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM
#  endif

And, again, -fexperimental-library is sufficient to end up
with !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) . [But so is
defined(_LIBCPP_BUILDING_LIBRARY) sufficient for that.]
Comment 4 Mark Millard 2025-11-27 04:02:31 UTC
(In reply to Mark Millard from comment #3)

See:

https://libcxx.llvm.org/Status/PSTL.html

To see just how incomplete the parallel STL support
is. So _LIBCPP_HAS_NO_INCOMPLETE_PSTL looks like
it will be defined for a long time in default
builds.