https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83431
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |diagnostic Status|UNCONFIRMED |NEW Last reconfirmed| |2017-12-14 CC| |msebor at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> --- That's right. String lengths are computed by and available only within the strlen pass, while sprintf/snprintf calls are processed by the sprintf pass. The two passes should probably be integrated somehow to benefit from each other's analysis. The example below shows where the integration would benefit in the strlen pass. $ cat d.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout d.c void f (char *d) { __builtin_sprintf (d, "%s", "123"); if (__builtin_strlen (d) != 3) // folded __builtin_abort (); // eliminated } void g (char *d) { int n = __builtin_sprintf (d, "%i", 123); if (n != 3) // folded __builtin_abort (); // eliminated } void h (char *d) { __builtin_sprintf (d, "%i", 123); if (__builtin_strlen (d) != 3) // not folded __builtin_abort (); // not eliminated } ;; Function f (f, funcdef_no=0, decl_uid=1892, cgraph_uid=0, symbol_order=0) f (char * d) { <bb 2> [local count: 1073741825]: __builtin_memcpy (d_3(D), "123", 4); [tail call] return; } ;; Function g (g, funcdef_no=1, decl_uid=1895, cgraph_uid=1, symbol_order=1) g (char * d) { <bb 2> [local count: 1073741825]: __builtin_sprintf (d_2(D), "%i", 123); [tail call] return; } ;; Function h (h, funcdef_no=2, decl_uid=1899, cgraph_uid=2, symbol_order=2) h (char * d) { long unsigned int _1; <bb 2> [local count: 1073741825]: __builtin_sprintf (d_3(D), "%i", 123); _1 = __builtin_strlen (d_3(D)); if (_1 != 3) goto <bb 3>; [0.00%] else goto <bb 4>; [99.96%] <bb 3> [count: 0]: __builtin_abort (); <bb 4> [local count: 1073312327]: return; }