https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82429
Bug ID: 82429
Summary: strcpy to stpcpy transformation disabled in strict
mode
Product: gcc
Version: 8.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: msebor at gcc dot gnu.org
Target Milestone: ---
In https://gcc.gnu.org/ml/gcc/2017-10/msg00010.html Jakub explains that the
strcpy to stpcpy optimizing transformation that is normally disabled in strict
conformance modes (e.g., with -std=c11 rather than -std=gnu11) is meant to be
enabled by defining _GNU_SOURCE, or _POSIX_C_SOURCE=200809, or
_XOPEN_SOURCE=700, or various other feature test macros that cause stpcpy to be
declared in system headers.
However, as the test case below shows (from
https://gcc.gnu.org/ml/gcc/2017-10/msg00015.html in the same thread), this is
not what actually happens. What appears to be necessary in addition to
defining one of the feature test macros above is also explicitly declaring the
stpcpy function in the program. A declaration alone in one of the system
headers is not sufficient. This seems like a bug. Explicitly declaring a
standard function that's already declared in a system header shouldn't have an
impact on the quality of emitted code.
$ cat z.c && gcc -O2 -S -Wall -Wextra -fdump-tree-optimized=/dev/stdout
-std=c11 -D_GNU_SOURCE z.c
#include <string.h>
#if STPCPY
extern char* stpcpy (char*, const char*);
#endif
void __attribute__ ((noclone)) f (char *d, const char *s)
{
strcpy (d, s); // with -D_GNU_SOURCE strcpy is expected to be transformed
to stpcpy
if (__builtin_strlen (d) != __builtin_strlen (s))
__builtin_abort ();
}
;; Function f (f, funcdef_no=4, decl_uid=1972, cgraph_uid=4, symbol_order=4)
__attribute__((noclone))
f (char * d, const char * s)
{
long unsigned int _1;
long unsigned int _2;
<bb 2> [100.00%] [count: INV]:
strcpy (d_4(D), s_5(D)); // strcpy not transformed to stpcpy
_1 = __builtin_strlen (d_4(D));
_2 = __builtin_strlen (s_5(D));
if (_1 != _2)
goto <bb 3>; [0.04%] [count: 0]
else
goto <bb 4>; [99.96%] [count: INV]
<bb 3> [0.04%] [count: 0]:
__builtin_abort ();
<bb 4> [99.96%] [count: INV]:
return;
}
$ gcc -O2 -S -Wall -Wextra -fdump-tree-optimized=/dev/stdout -std=c11
-D_GNU_SOURCE -DSTPCPY z.c
;; Function f (f, funcdef_no=4, decl_uid=1975, cgraph_uid=4, symbol_order=4)
__attribute__((noclone))
f (char * d, const char * s)
{
long unsigned int _1;
long unsigned int _2;
char * _8;
long unsigned int _9;
long unsigned int _10;
<bb 2> [100.00%] [count: INV]:
_8 = __builtin_stpcpy (d_4(D), s_5(D)); // strcpy transformed to stpcpy
_9 = (long unsigned int) _8;
_10 = (long unsigned int) d_4(D);
_1 = _9 - _10;
_2 = __builtin_strlen (s_5(D));
if (_1 != _2)
goto <bb 3>; [0.04%] [count: 0]
else
goto <bb 4>; [99.96%] [count: INV]
<bb 3> [0.04%] [count: 0]:
__builtin_abort ();
<bb 4> [99.96%] [count: INV]:
return;
}