https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80265
--- Comment #9 from Pedro Alves <palves at redhat dot com> ---
FWIW, I've tried to poke a bit more at this, to try to make it _not_ work, but
couldn't. It seems to always do what we need. These all work/compile too:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
constexpr int constexpr_strcmp(const char *s1, const char *s2)
{
while (*s1 != '\0' && *s1 == *s2)
{
s1++;
s2++;
}
if (*s1 < *s2)
return -1;
else if (*s1 > *s2)
return 1;
return 0;
}
constexpr int my_strcmp(const char *s1, const char *s2)
{
if (__builtin_constant_p (s1[0])
&& __builtin_constant_p (s2[0]))
return constexpr_strcmp (s1, s2);
return strcmp (s1, s2);
}
constexpr bool str4()
{
char s[4]= {};
int i = 0;
for (; i < 3; i++)
s[i] = i + 1;
return ce_char_traits<char>::length(s) == 3;
}
static_assert( str4() );
constexpr int foo (char x, char y)
{
char a[10] = "abcde";
a[2] = x;
a[4] = y;
return ce_char_traits<char>::length(a);
}
static_assert (foo ('1', '2') == 5);
static_assert (foo ('1', '\0') == 4);
bool runtime()
{
char s[] = "str";
s[0] = 'l';
s[1] = '\0';
return ce_char_traits<char>::length(s) == 1;
}
bool runtime2()
{
char s[4]= {};
int i = 0;
for (; i < 3; i++)
s[i] = i + 1;
return ce_char_traits<char>::length(s) == 3;
}
bool runtime3()
{
constexpr char s[] = "str";
return ce_char_traits<char>::length(s) == 1;
}
int main ()
{
assert (runtime ());
assert (runtime2 ());
assert (runtime3 ());
}
static_assert (my_strcmp("hello", "hello") == 0);
static_assert (my_strcmp("hello", "hell2") > 0);
static_assert (my_strcmp("hell2", "hello") < 0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
And I confirmed that "constexpr_strlen" / "constexpr_strcmp" are NOT emitted /
called as runtime functions, both at -O0 and -O2.