https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80265
--- Comment #6 from Pedro Alves <palves at redhat dot com> ---
Hmm. I'd argue that __builtin_constant_p should return true in that case,
since we're in a constexpr?
In any case, changing the test like this:
- if (__builtin_constant_p (s))
+ if (__builtin_constant_p (s[0]))
makes that work. I.e, this compiles:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <string>
constexpr size_t constexpr_strlen(const char* s)
{
size_t count = 0;
while (*s++)
count++;
return count;
}
template <class T>
struct ce_char_traits : std::char_traits<T>
{
using char_type = typename std::char_traits<T>::char_type;
static constexpr std::size_t length(const char_type* s) noexcept
{
if (__builtin_constant_p (s[0]))
return constexpr_strlen (s);
return __builtin_strlen (s);
}
};
static_assert (ce_char_traits<char>::length ("") == 0);
static_assert (ce_char_traits<char>::length ("hello") == 5);
static_assert (ce_char_traits<char>::length ("he\0llo") == 2);
static const char array[] = "foo";
static_assert (ce_char_traits<char>::length (array) == 3);
constexpr bool str()
{
char s[] = "str";
return ce_char_traits<char>::length(s) == 3;
}
constexpr bool str1()
{
char s[] = "str";
s[0] = 'l';
s[1] = '\0';
return ce_char_traits<char>::length(s) == 1;
}
constexpr bool str2()
{
char s[3] {};
s[0] = 'l';
s[1] = '\0';
return ce_char_traits<char>::length(s) == 1;
}
constexpr bool str3()
{
char s = {};
return ce_char_traits<char>::length(&s) == 0;
}
static_assert( str() );
static_assert( str1() );
static_assert( str2() );
static_assert( str3() );
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~