From 37112504009023d5723815092c075f68cda3b79d Mon Sep 17 00:00:00 2001 From: Ian Petersen Date: Thu, 1 Oct 2026 20:57:07 -0700 Subject: [PATCH] Address -Wpragma-clang-attribute When building stdexec with Clang and libc++ version 23+, `-Wpragma-clang-attribute` causes many errors that look like this: ``` error: unused attribute '__visibility__' in '#pragma clang attribute push' region [-Werror,-Wpragma-clang-attribute] ``` attributable to uses of the `STDEXEC_NAMESPACE_STD_BEGIN` macro. stdexec only uses that macro to forward-declare non-functions, and the attribute is only applicable to functions, so the warning fires on every region where stdexec forward-declares things in `std`. This diff addresses the problem by modifying the `STDEXEC_NAMESPACE_STD_BEGIN`/`_END` macros to push and pop a `-Wno-pragma-clang-attribute` setting around the region whenever building with Clang and libc++. GCC also fails when building with libc++ version 23+, but the failure is because GCC doesn't recognize the `#pragma clang attribute push` pragma and so fails with an unsuppressable warning-as-error; the tip of `main` in libc++ resolves this problem by only emitting the pragma when compiling with Clang. --- include/stdexec/__detail/__config.hpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/include/stdexec/__detail/__config.hpp b/include/stdexec/__detail/__config.hpp index 0ec78620b..5724e67d3 100644 --- a/include/stdexec/__detail/__config.hpp +++ b/include/stdexec/__detail/__config.hpp @@ -178,7 +178,29 @@ import std; // It is used when forward-declaring a standard library type or function, which is not // portable but sometimes necessary to avoid pulling in a large header when a fwd decl // would do. -#if defined(_LIBCPP_VERSION) +// +// libc++ 23's _LIBCPP_BEGIN_NAMESPACE_STD opens a `#pragma clang attribute push` region +// that applies only to functions, and _LIBCPP_END_NAMESPACE_STD closes it. When the +// region is opened from a non-system header and declares no functions (as in our +// forward-declaration blocks), Clang reports the pushed attribute as unused under +// -Wpragma-clang-attribute, so we suppress that warning for the duration of the block. +// Only Clang implements `#pragma clang attribute`, so only Clang can emit that warning; +// hence the STDEXEC_CLANG() guard. +// +// Known gap: libc++ 23 emits those pragmas for every compiler (later versions emit them +// only for Clang-based compilers), so GCC with libc++ 23 reports them under +// -Wunknown-pragmas instead. GCC does not apply a diagnostic pragma to another pragma +// from the same macro expansion, so that can't be suppressed here. +// +// This uses STDEXEC_PRAGMA directly rather than STDEXEC_PRAGMA_PUSH() and friends +// because those are defined further down, after the first use of these macros below. +#if defined(_LIBCPP_VERSION) && STDEXEC_CLANG() +# define STDEXEC_NAMESPACE_STD_BEGIN \ + STDEXEC_PRAGMA(clang diagnostic push) \ + STDEXEC_PRAGMA(clang diagnostic ignored "-Wpragma-clang-attribute") \ + _LIBCPP_BEGIN_NAMESPACE_STD +# define STDEXEC_NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD STDEXEC_PRAGMA(clang diagnostic pop) +#elif defined(_LIBCPP_VERSION) # define STDEXEC_NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD # define STDEXEC_NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD #elif defined(__GLIBCXX__)