4848// macro name; nothing, otherwise.
4949#if defined(__NVCC__)
5050# define STDEXEC_NVCC (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
51+ # define STDEXEC_NVCC_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__)
5152#elif defined(__EDG__)
5253# define STDEXEC_EDG (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
54+ # define STDEXEC_EDG_VERSION __EDG_VERSION__
5355# if defined(__NVCOMPILER)
5456# define STDEXEC_NVHPC (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
57+ # define STDEXEC_NVHPC_VERSION (__NVCOMPILER_MAJOR__ * 100 + __NVCOMPILER_MINOR__)
5558# endif
5659# if defined(__INTELLISENSE__)
5760# define STDEXEC_INTELLISENSE (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
5861# define STDEXEC_MSVC_HEADERS (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
5962# endif
6063#elif defined(__clang__)
6164# define STDEXEC_CLANG (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
65+ # define STDEXEC_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
6266# if defined(_MSC_VER)
6367# define STDEXEC_CLANG_CL (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
6468# endif
6569# if defined(__apple_build_version__)
6670# define STDEXEC_APPLE_CLANG (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
71+ // Apple clang version is encoded as major * 1000000 + minor * 1000 + patch. We ignore the patch
72+ // version here, as it is not relevant for the purposes of this library.
73+ # define STDEXEC_APPLE_CLANG_VERSION (__apple_build_version__ / 1000 )
6774# endif
6875#elif defined(__GNUC__)
6976# define STDEXEC_GCC (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
77+ # define STDEXEC_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
7078#elif defined(_MSC_VER)
7179# define STDEXEC_MSVC (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
7280# define STDEXEC_MSVC_HEADERS (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
81+ # define STDEXEC_MSVC_VERSION _MSC_VER
7382#endif
7483
7584#ifndef STDEXEC_NVCC
103112# define STDEXEC_INTELLISENSE (...) STDEXEC_HEAD_OR_NULL(0 , __VA_ARGS__)
104113#endif
105114
106- #if STDEXEC_NVHPC()
107- # define STDEXEC_NVHPC_VERSION () (__NVCOMPILER_MAJOR__ * 100 + __NVCOMPILER_MINOR__)
108- #endif
109-
110115// //////////////////////////////////////////////////////////////////////////////////////////////////
111116#if defined(__CUDACC__) || STDEXEC_NVHPC()
112117# define STDEXEC_CUDA_COMPILATION (...) STDEXEC_HEAD_OR_TAIL(1 , __VA_ARGS__)
@@ -173,13 +178,25 @@ namespace __coro = std::experimental;
173178
174179#if STDEXEC_NVHPC()
175180// NVBUG #4067067: NVHPC does not fully support [[no_unique_address]]
176- # define STDEXEC_ATTR_WHICH_3 (_ATTR ) /* nothing*/
181+ # if STDEXEC_NVHPC_VERSION < 23'05
182+ # define STDEXEC_ATTR_WHICH_3 (_ATTR ) /* nothing*/
183+ # else
184+ # define STDEXEC_ATTR_WHICH_3 (_ATTR ) [[no_unique_address]]
185+ # endif
186+ #elif STDEXEC_CLANG_CL()
187+ // clang-cl does not support [[no_unique_address]]: https://reviews.llvm.org/D110485
188+ # if STDEXEC_CLANG_VERSION < 18'01 // TODO: Find the version that started supporting [[msvc::no_unique_address]]
189+ # define STDEXEC_ATTR_WHICH_3 (_ATTR ) /* nothing*/
190+ # else
191+ # define STDEXEC_ATTR_WHICH_3 (_ATTR ) [[msvc::no_unique_address]]
192+ # endif
177193#elif STDEXEC_MSVC()
178194// MSVCBUG https://developercommunity.visualstudio.com/t/Incorrect-codegen-when-using-msvc::no_/10452874
179- # define STDEXEC_ATTR_WHICH_3 (_ATTR ) // [[msvc::no_unique_address]]
180- #elif STDEXEC_CLANG_CL()
181- // clang-cl does not support: https://reviews.llvm.org/D110485
182- # define STDEXEC_ATTR_WHICH_3 (_ATTR ) // [[msvc::no_unique_address]]
195+ # if STDEXEC_MSVC_VERSION < 19'43
196+ # define STDEXEC_ATTR_WHICH_3 (_ATTR ) /* nothing*/
197+ # else
198+ # define STDEXEC_ATTR_WHICH_3 (_ATTR ) [[msvc::no_unique_address]]
199+ # endif
183200#else
184201# define STDEXEC_ATTR_WHICH_3 (_ATTR ) [[no_unique_address]]
185202#endif
@@ -190,7 +207,7 @@ namespace __coro = std::experimental;
190207#elif STDEXEC_CLANG()
191208# define STDEXEC_ATTR_WHICH_4 (_ATTR ) \
192209 __attribute__ ((__always_inline__, __artificial__, __nodebug__)) inline
193- #elif defined(__GNUC__ )
210+ #elif STDEXEC_GCC( )
194211# define STDEXEC_ATTR_WHICH_4 (_ATTR ) __attribute__((__always_inline__, __artificial__)) inline
195212#else
196213# define STDEXEC_ATTR_WHICH_4 (_ATTR ) /* nothing*/
@@ -272,7 +289,7 @@ namespace __coro = std::experimental;
272289# define STDEXEC_IS_TRIVIALLY_COPYABLE (...) std::is_trivially_copyable_v<__VA_ARGS__>
273290#endif
274291
275- #if STDEXEC_HAS_BUILTIN(__is_base_of) || (_MSC_VER >= 1914 )
292+ #if STDEXEC_HAS_BUILTIN(__is_base_of) || (STDEXEC_MSVC_VERSION >= 19'14 )
276293# define STDEXEC_IS_BASE_OF (...) __is_base_of(__VA_ARGS__)
277294#else
278295# define STDEXEC_IS_BASE_OF (...) std::is_base_of_v<__VA_ARGS__>
@@ -371,17 +388,19 @@ namespace stdexec {
371388#endif
372389
373390// Before gcc-12, gcc really didn't like tuples or variants of immovable types
374- #if STDEXEC_GCC() && (__GNUC__ < 12)
391+ #if STDEXEC_GCC() && (STDEXEC_GCC_VERSION < 12'00 )
375392# define STDEXEC_IMMOVABLE (_XP ) _XP(_XP&&)
376393#else
377394# define STDEXEC_IMMOVABLE (_XP ) _XP(_XP&&) = delete
378395#endif
379396
397+ #if STDEXEC_GCC()
380398// BUG (gcc#98995): copy elision fails when initializing a [[no_unique_address]] field
381399// from a function returning an object of class type by value.
382- //
383400// See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98995
384- #if STDEXEC_GCC()
401+ # define STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS
402+ #elif STDEXEC_CLANG() && (__clang_major__ >= 15 && __clang_major__ < 19)
403+ // See https://github.com/llvm/llvm-project/issues/93563
385404# define STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS
386405#else
387406# define STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS STDEXEC_ATTRIBUTE (no_unique_address)
@@ -401,7 +420,7 @@ namespace stdexec {
401420// Some compilers turn on pack indexing in pre-C++26 code. We want to use it if it is
402421// available. Pack indexing is disabled for clang < 20 because of:
403422// https://github.com/llvm/llvm-project/issues/116105
404- #if defined(__cpp_pack_indexing) && !STDEXEC_NVCC() && !(STDEXEC_CLANG() && __clang_major__ < 20)
423+ #if defined(__cpp_pack_indexing) && !STDEXEC_NVCC() && !(STDEXEC_CLANG() && STDEXEC_CLANG_VERSION < 20'00 )
405424# define STDEXEC_HAS_PACK_INDEXING () 1
406425#else // ^^^ has pack indexing ^^^ / vvv no pack indexing vvv
407426# define STDEXEC_HAS_PACK_INDEXING () 0
@@ -416,7 +435,7 @@ namespace stdexec {
416435// Before clang-16, clang did not like libstdc++'s ranges implementation
417436#if __has_include(<ranges>) && \
418437 (defined (__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L ) && \
419- (!STDEXEC_CLANG() || __clang_major__ >= 16 || defined (_LIBCPP_VERSION))
438+ (!STDEXEC_CLANG() || STDEXEC_CLANG_VERSION >= 16'00 || defined (_LIBCPP_VERSION))
420439# define STDEXEC_HAS_STD_RANGES () 1
421440#else
422441# define STDEXEC_HAS_STD_RANGES () 0
@@ -461,7 +480,7 @@ namespace stdexec {
461480 }
462481
463482// GCC 13 implements lexical friendship, but it is incomplete. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111018
464- #if STDEXEC_CLANG() // || (STDEXEC_GCC() && __GNUC__ >= 13)
483+ #if STDEXEC_CLANG() // || (STDEXEC_GCC() && STDEXEC_GCC_VERSION >= 13'00 )
465484# define STDEXEC_FRIENDSHIP_IS_LEXICAL () 1
466485#else
467486# define STDEXEC_FRIENDSHIP_IS_LEXICAL () 0
0 commit comments