Skip to content

fix c++20 build failure with pre-c++20 standard libraries - #268

Merged
kevinushey merged 1 commit into
masterfrom
bugfix/tbb-cpp20-concepts-guard
Jul 27, 2026
Merged

fix c++20 build failure with pre-c++20 standard libraries#268
kevinushey merged 1 commit into
masterfrom
bugfix/tbb-cpp20-concepts-guard

Conversation

@kevinushey

@kevinushey kevinushey commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Fixes the installation failure on CRAN's r-release-macos-x86_64 machine
(install log).

The problem

That builder is the only flavor pairing a C++20 language mode with a pre-C++20 standard library:

flavor compiler SDK result
r-release-macos-x86_64 Apple clang 14.0.3 MacOSX11.3.1.sdk ERROR
r-release-macos-arm64 Apple clang 17.0.0 MacOSX14.5.sdk OK

R's Makeconf there compiles with -std=gnu++20 (nothing in our configure / Makevars.in sets a
standard). Apple clang 14 accepts that and defines __cplusplus == 202002L, but the libc++ bundled in
the 11.3 SDK does not provide the C++20 iterator concepts.

The bundled oneTBB selected its concepts-based iterator dispatch on the wrong macro:

#if __TBB_CPP20_PRESENT      // == (__TBB_LANG >= 202002L) -- a *language* check
...
    std::conditional_t<std::random_access_iterator<It>,   // a *library* feature

so the concepts branch was taken and failed with no member named 'random_access_iterator' in namespace 'std'.

Every other C++20 library dependency in these headers is already gated correctly -- the <concepts>
includes in flow_graph.h, _range_common.h and _mutex_common.h are behind
__TBB_CPP20_CONCEPTS_PRESENT, and __TBB_CPP20_COMPARISONS_PRESENT checks both the language and
library feature-test macros. parallel_for_each.h was the lone offender.

Note this is not just our own tbb.cpp: we ship these headers in inst/include, so any downstream
package compiling under C++20 on that toolchain hits it too.

The fix

Switch the guard to __TBB_CPP20_CONCEPTS_PRESENT, mirroring the upstream fix from
oneTBB PR #1611
(issue #1552), first released in oneTBB
2022.1.0. We bundle 2022.0.0, which predates it; the patch can be dropped once the bundled oneTBB is
updated past that.

__TBB_CPP20_CONCEPTS_PRESENT is hard-coded to 0 for clang in this TBB version (upstream master
still does this: #if !(__clang__) && defined(__cpp_concepts) && defined(__cpp_lib_concepts)), so
clang builds fall back to the pre-C++20 iterator_category tag dispatch -- which is already what
clang does for every other constraint in TBB, so this is consistent rather than a regression.

The change is recorded in patches/cpp20_concepts.diff, following the existing convention.

Verification

  • -fsyntax-only on src/tbb.cpp and on a standalone tbb::parallel_for_each TU under gnu++17,
    gnu++20 and gnu++23: all clean.
  • Full R CMD INSTALL --preclean succeeds, compiling with -std=c++20.
  • All 9 scripts under tests/ pass.
  • Runtime check via sourceCpp under -std=c++20: tbb::parallel_for_each over a std::vector
    (random-access dispatch) and a std::list (forward dispatch) both produce correct results, so the
    fallback tag dispatch works at runtime and not merely syntactically.
  • static_assert(__TBB_CPP20_CONCEPTS_PRESENT == 0) against the bundled _config.h passes on clang,
    confirming the concepts branch is now unreachable there regardless of SDK.

Reproduced locally against the macOS 11.3 SDK

Confirmed end-to-end by compiling against the actual SDK CRAN uses (extracted from
phracker/MacOSX-SDKs, which ships
_LIBCPP_VERSION 12000 -- no __iterator/concepts.h, no std::random_access_iterator):

  • Before the fix, -isysroot MacOSX11.3.sdk -arch x86_64 -std=gnu++20 reproduces the CRAN
    failure exactly: the same 7 errors at the same lines (429, 430, 437, 503, 631).
  • After the fix, the same command compiles clean.
  • All 48 public oneapi/tbb/*.h headers (including the three preview-gated ones) compile clean
    against that SDK at both gnu++17 and gnu++20, so no second missing C++20 library facility is
    lurking behind the first error.
  • src/tbb.cpp and a bare #include <RcppParallel.h> TU both compile clean against that SDK at
    gnu++17 and gnu++20, covering the downstream include surface.

…ESENT

parallel_for_each.h selected its concepts-based iterator_tag_dispatch on
__TBB_CPP20_PRESENT, which only tests the language mode (__TBB_LANG >=
202002L). Toolchains that accept -std=c++20 but ship a pre-C++20 standard
library then take the concepts branch and fail to find
std::random_access_iterator; this broke installation on CRAN's macOS
x86_64 machines, which pair Apple clang 14 with the macOS 11.3 SDK.

Every other C++20 library dependency in these headers is already gated on
__TBB_CPP20_CONCEPTS_PRESENT (or, for <compare>, on both the language and
library feature-test macros), so parallel_for_each.h was the lone
offender.

This mirrors the upstream fix from oneTBB PR #1611 (issue #1552), first
released in oneTBB 2022.1.0, and can be dropped once the bundled oneTBB
is updated past 2022.0.0.
@kevinushey
kevinushey merged commit 39afcb3 into master Jul 27, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant