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() ); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~