As pointed out in the comments it seems that even GCC and clang behave different here so the conclusion is that the definition of the compiler builtin is way to loose in order to expect it to align with the definition of a C++ constant expression.
Still, I found a solution for my specific problem. Previously, I was trying to pass a constexpr string literal to the os_signpost_interval_begin
macro like
constexpr std::string_view s = "foo"; // (actually a static constexpr class member)
os_signpost_interval_begin (log, id, s.data(), "begin");
This triggered a static assertion hidden deeper in the that macro since __builtin_constant_p (s.data())
evaluated to false, which then led me to create that test case presented in the original question.
In the meantime, I let my IDE inline the invocation of the os_signpost_interval_begin
macro, which revealed some more context of that assertion. We find a macro like this being used
#define OS_LOG_STRING(_ns, _var, _str) \
_Static_assert(__builtin_constant_p(_str), \
"format/label/description argument must be a string constant"); \
__attribute__((section("__TEXT,__oslogstring,cstring_literals"),internal_linkage)) \
static const char _var[] __asm(OS_STRINGIFY(OS_CONCAT(LOS_##_ns, __COUNTER__))) = _str
so as far as I get it, that string literal variable is placed into a specific section of the binary where the profiler will expect it. Creating that variable this way by passing a const char*
pointer as string to that macro rather than a literal would indeed not yield to code that compiles, so it seems that the assertion here makes some sense for this very particular use case.
As a workaround, I replicated the content of the macro myself inside a function template that takes a std::index_sequence
of the string length and generate an assignment from a compile time static string by unpacking it character by character into an initializer list through an index sequence like
template <size_t... i>
void signpostIntervalBeginHelper (const std::index_sequence<i...>&)
{
//...
// sLen is a constexpr constant member available in my class which equals the length of s
__attribute__((section("__TEXT,__oslogstring,cstring_literals"), internal_linkage)) static const char _os_name_str[sLen] __asm(OS_STRINGIFY(OS_CONCAT(LOS_##_ns, __COUNTER__))) = { s[i]... };
//...
}
void signpostInvervalBegin()
{
signpostInveralBeginHelper (std::make_index_sequence<sLen>());
}
which proved to solve my problem.