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

Reply via email to