On 08/27/2018 02:29 AM, Richard Biener wrote: > On Sun, Aug 26, 2018 at 7:26 AM Jeff Law <l...@redhat.com> wrote: >> >> On 08/24/2018 09:58 AM, Martin Sebor wrote: >>> The warning suppression for -Wstringop-truncation looks for >>> the next statement after a truncating strncpy to see if it >>> adds a terminating nul. This only works when the next >>> statement can be reached using the Gimple statement iterator >>> which isn't until after gimplification. As a result, strncpy >>> calls that truncate their constant argument that are being >>> folded to memcpy this early get diagnosed even if they are >>> followed by the nul assignment: >>> >>> const char s[] = "12345"; >>> char d[3]; >>> >>> void f (void) >>> { >>> strncpy (d, s, sizeof d - 1); // -Wstringop-truncation >>> d[sizeof d - 1] = 0; >>> } >>> >>> To avoid the warning I propose to defer folding strncpy to >>> memcpy until the pointer to the basic block the strnpy call >>> is in can be used to try to reach the next statement (this >>> happens as early as ccp1). I'm aware of the preference to >>> fold things early but in the case of strncpy (a relatively >>> rarely used function that is often misused), getting >>> the warning right while folding a bit later but still fairly >>> early on seems like a reasonable compromise. I fear that >>> otherwise, the false positives will drive users to adopt >>> other unsafe solutions (like memcpy) where these kinds of >>> bugs cannot be as readily detected. >>> >>> Tested on x86_64-linux. >>> >>> Martin >>> >>> PS There still are outstanding cases where the warning can >>> be avoided. I xfailed them in the test for now but will >>> still try to get them to work for GCC 9. >>> >>> gcc-87028.diff >>> >>> >>> PR tree-optimization/87028 - false positive -Wstringop-truncation strncpy >>> with global variable source string >>> gcc/ChangeLog: >>> >>> PR tree-optimization/87028 >>> * gimple-fold.c (gimple_fold_builtin_strncpy): Avoid folding when >>> statement doesn't belong to a basic block. >>> * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Handle MEM_REF on >>> the left hand side of assignment. >>> >>> gcc/testsuite/ChangeLog: >>> >>> PR tree-optimization/87028 >>> * c-c++-common/Wstringop-truncation.c: Remove xfails. >>> * gcc.dg/Wstringop-truncation-5.c: New test. >>> >>> diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c >>> index 07341eb..284c2fb 100644 >>> --- a/gcc/gimple-fold.c >>> +++ b/gcc/gimple-fold.c >>> @@ -1702,6 +1702,11 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator >>> *gsi, >>> if (tree_int_cst_lt (ssize, len)) >>> return false; >>> >>> + /* Defer warning (and folding) until the next statement in the basic >>> + block is reachable. */ >>> + if (!gimple_bb (stmt)) >>> + return false; >> I think you want cfun->cfg as the test here. They should be equivalent >> in practice. > > Please do not add 'cfun' references. Note that the next stmt is also > accessible > when there is no CFG. I guess the issue is that we fold this during > gimplification where the next stmt is not yet "there" (but still in GENERIC)? That was my assumption. I almost suggested peeking at gsi_next and avoiding in that case.
> > We generally do not want to have unfolded stmts in the IL when we can avoid > that > which is why we fold most stmts during gimplification. We also do that > because > we now do less folding on GENERIC. But an unfolded call in the IL should always be safe and we've got plenty of opportunities to fold it later. Jeff