The strlen call in f() below compiles with no warning and is successfully folded to a constant, but the equivalent call in g() triggers two spurious instances of the same warning and is not folded. The warning is new in GCC 9 so GCC 8 compiles both functions without one, and folds neither call, $ cat a.c && gcc -O2 -S -Wall -Wextra -fdump-tree-optimized=/dev/stdout a.c struct A { char n, s[]; }; const struct A a1 = { 3, "321" }; int f (void) { return __builtin_strlen (a1.s); // no warning, folded to 3 } const struct A a2 = { 3, { 3, 2, 1, 0 } }; int g (void) { return __builtin_strlen (a2.s); // bogus warning, not folded } a.c: In function ‘g’: a.c:14:30: warning: ‘strlen’ argument missing terminating nul [-Wstringop-overflow=] 14 | return __builtin_strlen (a2.s); // bogus warning, not folded | ~~^~ a.c:10:16: note: referenced argument declared here 10 | const struct A a2 = { 3, { 3, 2, 1, 0 } }; | ^~ a.c:14:30: warning: ‘strlen’ argument missing terminating nul [-Wstringop-overflow=] 14 | return __builtin_strlen (a2.s); // bogus warning, not folded | ~~^~ a.c:10:16: note: referenced argument declared here 10 | const struct A a2 = { 3, { 3, 2, 1, 0 } }; | ^~ ;; Function f (f, funcdef_no=0, decl_uid=1910, cgraph_uid=1, symbol_order=1) f () { <bb 2> [local count: 1073741824]: return 3; } ;; Function g (g, funcdef_no=1, decl_uid=1914, cgraph_uid=2, symbol_order=3) g () { long unsigned int _1; int _3; <bb 2> [local count: 1073741824]: _1 = __builtin_strlen (&a2.s); _3 = (int) _1; return _3; }
Patch: https://gcc.gnu.org/ml/gcc-patches/2019-08/msg01202.html
A subset of the patch referenced in comment #1 that deals with just this issue: https://gcc.gnu.org/ml/gcc-patches/2019-08/msg01517.html
Author: msebor Date: Thu Aug 22 23:09:26 2019 New Revision: 274837 URL: https://gcc.gnu.org/viewcvs?rev=274837&root=gcc&view=rev Log: PR middle-end/91490 - bogus argument missing terminating nul warning on strlen of a flexible array member gcc/c-family/ChangeLog: PR middle-end/91490 * c-common.c (braced_list_to_string): Add argument and overload. Handle flexible length arrays and unions. gcc/testsuite/ChangeLog: PR middle-end/91490 * c-c++-common/Warray-bounds-7.c: New test. * gcc.dg/Warray-bounds-39.c: Expect either -Warray-bounds or -Wstringop-overflow. * gcc.dg/strlenopt-78.c: New test. gcc/ChangeLog: PR middle-end/91490 * builtins.c (c_strlen): Rename argument and introduce new local. Set no-warning bit on original argument. * expr.c (string_constant): Pass argument type to fold_ctor_reference. Fold empty and zero constructors into empty strings. * gimple-fold.c (fold_nonarray_ctor_reference): Return a STRING_CST for missing initializers. * tree.c (build_string_literal): Handle optional argument. * tree.h (build_string_literal): Add defaulted argument. * gimple-ssa-warn-restrict.c (maybe_diag_access_bounds): Check no-warning bit on original expression. Added: trunk/gcc/testsuite/c-c++-common/Warray-bounds-7.c trunk/gcc/testsuite/gcc.dg/strlenopt-78.c Modified: trunk/gcc/ChangeLog trunk/gcc/builtins.c trunk/gcc/c-family/ChangeLog trunk/gcc/c-family/c-common.c trunk/gcc/expr.c trunk/gcc/gimple-fold.c trunk/gcc/gimple-ssa-warn-restrict.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/gcc.dg/Warray-bounds-39.c trunk/gcc/tree.c trunk/gcc/tree.h
Fixed in r274837. I'm not sure this should be backported. It suppresses bogus warnings but also introduces new warnings for invalid code.
*** Bug 91667 has been marked as a duplicate of this bug. ***
The same bogus warning ist produced by "g++ -Wall" with the C++ code below. Note that flexible array members are not involved there. GCC 9.2 is affected: https://godbolt.org/z/j9m4XS GCC 10 seems fixed: https://godbolt.org/z/DPrR1Z ////////////////////////////////////////////////////////////////////////////// struct two_chars_t {// std::array<char, 2> char data_[2]; constexpr const char* data() const { return data_; } }; constexpr two_chars_t global_x0 = two_chars_t{'x', '\0'}; int main() { constexpr const char* pointer = global_x0.data(); static_assert(pointer[0] == 'x'); static_assert(pointer[1] == '\0'); return __builtin_strlen(pointer); } //////////////////////////////////////////////////////////////////////////////
GCC 9.3.0 has been released, adjusting target milestone.
Bug 96934 is potentially related to this issue, but I have also found a miscompilation of strcmp call that is possibly related.
GCC 9.4 is being released, retargeting bugs to GCC 9.5.
I'm no longer planning to backport the fix.
Fixed in GCC 10.