G++ accepts most calls to __builtin_strcmp with constant arguments in constexpr contexts, except when the intrinsic is invoked on local arrays defined in a constexpr function. The test case below shows a number of accepted calls along with the one that's incorrectly rejected. $ cat u.c && /home/msebor/build/gcc-trunk-git/gcc/xgcc -B/home/msebor/build/gcc-trunk-git/gcc -Wall -Wextra -Wpedantic -xc++ u.c constexpr int f0 () { return __builtin_strcmp ("a", "b"); } constexpr int f1 () { const char a [] = "a"; const char b [] = "b"; return __builtin_strcmp (a, b); } constexpr int f2 (const char *a, const char *b) { int d = 0; do { d = *b - *a; } while (*a++ && *b++); return d; } constexpr int f3 () { const char s [] = "a"; const char t [] = "b"; const char *a = s; const char *b = t; int d = 0; do { d = *b - *a; } while (*a++ && *b++); return d; } constexpr char a [] = "a"; constexpr char b [] = "b"; constexpr int i0 = __builtin_strcmp ("a", "b"); constexpr int i1 = __builtin_strcmp (a, b); constexpr int i2 = f1 (); constexpr int i3 = f2 (a, b); constexpr int i4 = f3 (); u.c:42:23: in constexpr expansion of ‘f1()’ u.c:10:27: error: ‘__builtin_strcmp(((const char*)(& a)), ((const char*)(& b)))’ is not a constant expression return __builtin_strcmp (a, b); ~~~~~~~~~~~~~~~~~^~~~~~
The same limitation affects other string builtins such as __builtin_strlen or __builtin_strchr. $ cat cst.C && /home/msebor/build/gcc-6-branch/gcc/xgcc -B/home/msebor/build/gcc-6-branch/gcc -S -Wall -Wextra -Wpedantic cst.C -fdump-tree-optimized=/dev/stdout -o/dev/stdout constexpr int chr (int c) { const char a[] = "123"; return __builtin_strchr (a, c) - a; } constexpr int i = chr ('3'); constexpr int cmp (const char *a) { const char b[] = "123"; return __builtin_strcmp (a, b); } constexpr int j = cmp ("345"); constexpr unsigned len () { const char s[] = "123"; return __builtin_strlen (s); } constexpr unsigned n = len (); .file "cst.C" cst.C:7:23: in constexpr expansion of ‘chr(51)’ cst.C:4:27: error: ‘__builtin_strchr(((const char*)(& a)), 51)’ is not a constant expression return __builtin_strchr (a, c) - a; ~~~~~~~~~~~~~~~~~^~~~~~ cst.C:15:23: in constexpr expansion of ‘cmp(((const char*)"345"))’ cst.C:12:27: error: ‘__builtin_strcmp(((const char*)"345"), ((const char*)(& b)))’ is not a constant expression return __builtin_strcmp (a, b); ~~~~~~~~~~~~~~~~~^~~~~~ cst.C:23:28: in constexpr expansion of ‘len()’ cst.C:20:27: error: ‘__builtin_strlen(((const char*)(& s)))’ is not a constant expression return __builtin_strlen (s); ~~~~~~~~~~~~~~~~~^~~
Confirmed, I'm also seeing this in C++20 mode. This affects libc++'s `char_traits<char>::length(const char *)`. Example test case: https://godbolt.org/z/MTq1ex
We are having to add a workaround in libc++ to implement constexpr std::string: https://reviews.llvm.org/D115795 It would be awesome if this could be fixed! (if so, please drop us a line and we'll remove our workaround)
Our std::char_traits has similar branches for constant evaluation (and the rest of the library does too for memcpy etc.)
I'm not working on this anymore.