| Summary: | bogus error __builtin_strcmp is not a constant expression in a constexpr function | ||
|---|---|---|---|
| Product: | gcc | Reporter: | Martin Sebor <msebor> |
| Component: | c++ | Assignee: | Not yet assigned to anyone <unassigned> |
| Status: | NEW --- | ||
| Severity: | normal | CC: | arthur.j.odwyer, daniel.kruegler, ldionne.2, webrown.cpp |
| Priority: | P3 | Keywords: | rejects-valid |
| Version: | 6.0 | ||
| Target Milestone: | --- | ||
| See Also: |
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82915 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106889 |
||
| Host: | Target: | ||
| Build: | Known to work: | ||
| Known to fail: | 5.3.0, 6.1.0, 7.0 | Last reconfirmed: | 2016-06-08 00:00:00 |
| Bug Depends on: | |||
| Bug Blocks: | 55004 | ||
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. |
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); ~~~~~~~~~~~~~~~~~^~~~~~