Hi! As mentioned on IRC, we can actually now use ERF_RETURN*_ARG* to find out what functions are pass through (except for __builtin_assume_aligned, which is pass through but we never want to propagate the arg to the result early, as the result contains additional information, so it isn't RET1).
While cleaning this up, I run into a bug in the function, BUILT_IN_STPNCPY_CHK obviously isn't a pass-through function, so I've also added a testcase that FAILs without this patch and succeeds with it. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? For release branches I'd just remove the BUILT_IN_STPNCPY_CHK case and add testcase. 2017-11-23 Jakub Jelinek <ja...@redhat.com> * tree-object-size.c (pass_through_call): Use gimple_call_return_flags ERF_RETURN*ARG* for builtins other than BUILT_IN_ASSUME_ALIGNED, check for the latter with gimple_call_builtin_p. Do not handle BUILT_IN_STPNCPY_CHK which is not a pass through call. * gcc.dg/builtin-object-size-18.c: New test. --- gcc/tree-object-size.c.jj 2017-10-20 09:16:10.000000000 +0200 +++ gcc/tree-object-size.c 2017-11-23 16:23:24.544741945 +0100 @@ -464,34 +464,17 @@ alloc_object_size (const gcall *call, in static tree pass_through_call (const gcall *call) { - tree callee = gimple_call_fndecl (call); + unsigned rf = gimple_call_return_flags (call); + if (rf & ERF_RETURNS_ARG) + { + unsigned argnum = rf & ERF_RETURN_ARG_MASK; + if (argnum < gimple_call_num_args (call)) + return gimple_call_arg (call, argnum); + } - if (callee - && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) - switch (DECL_FUNCTION_CODE (callee)) - { - case BUILT_IN_MEMCPY: - case BUILT_IN_MEMMOVE: - case BUILT_IN_MEMSET: - case BUILT_IN_STRCPY: - case BUILT_IN_STRNCPY: - case BUILT_IN_STRCAT: - case BUILT_IN_STRNCAT: - case BUILT_IN_MEMCPY_CHK: - case BUILT_IN_MEMMOVE_CHK: - case BUILT_IN_MEMSET_CHK: - case BUILT_IN_STRCPY_CHK: - case BUILT_IN_STRNCPY_CHK: - case BUILT_IN_STPNCPY_CHK: - case BUILT_IN_STRCAT_CHK: - case BUILT_IN_STRNCAT_CHK: - case BUILT_IN_ASSUME_ALIGNED: - if (gimple_call_num_args (call) >= 1) - return gimple_call_arg (call, 0); - break; - default: - break; - } + /* __builtin_assume_aligned is intentionally not marked RET1. */ + if (gimple_call_builtin_p (call, BUILT_IN_ASSUME_ALIGNED)) + return gimple_call_arg (call, 0); return NULL_TREE; } --- gcc/testsuite/gcc.dg/builtin-object-size-18.c.jj 2017-11-23 16:33:25.723389685 +0100 +++ gcc/testsuite/gcc.dg/builtin-object-size-18.c 2017-11-23 16:34:02.930934647 +0100 @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* __stpncpy_chk could return buf up to buf + 64, so + the minimum object size might be far smaller than 64. */ +/* { dg-final { scan-tree-dump-not "return 64;" "optimized" } } */ + +typedef __SIZE_TYPE__ size_t; + +size_t +foo (const char *p, size_t s, size_t t) +{ + char buf[64]; + char *q = __builtin___stpncpy_chk (buf, p, s, t); + return __builtin_object_size (q, 2); +} Jakub