On 9/14/18, Martin Sebor wrote: > As I said above, this happens during the dom walk in the ccp > pass: > > substitute_and_fold_dom_walker walker (CDI_DOMINATORS, this); > walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun)); > > The warning is issued during the walker.walk() call as > strncpy is being folded into memcpy. The prior assignments are > only propagated later, when the next statement after the strncpy > call is reached. It happens in > substitute_and_fold_dom_walker::before_dom_children(). So during > the strncpy folding we see the next statement as: > > MEM[(struct S *)_1].a[n_7] = 0; > > After the strncpy call is transformed to memcpy, the assignment > above is transformed to > > MEM[(struct S *)_8].a[3] = 0; > > >> If they're only discovered as copies within the pass where you're trying >> to issue the diagnostic, then you'd want to see if the pass has any >> internal structures that tell you about equivalences. > > > I don't know if this is possible. I don't see any APIs in > tree-ssa-propagate.h that would let me query the internal data > somehow to find out during folding (when the warning is issued).
Well, if I see this right, the CCP is doing tree transformations while from the folding of strncpy the predicate maybe_diag_stxncpy_trunc is called, and sees inconsistent information, in the tree, and therefore it issues a warning. I understand that walking the references is fragile at least in this state. But why not just prevent warnings when this is called from CCP? Like this? Bootstrapped and reg-tested on x86_64-pc-linux-gnu. Is it OK for trunk? Thanks Bernd.
gcc: 2018-09-15 Bernd Edlinger <bernd.edlin...@hotmail.de> PR tree-optimization/84561 * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Bail out if called from CCP. testsuite: 2018-09-15 Martin Sebor <mse...@redhat.com> PR tree-optimization/84561 * gcc.dg/Wstringop-truncation-6.c: New test. diff -Npur gcc/tree-ssa-strlen.c gcc/tree-ssa-strlen.c --- gcc/tree-ssa-strlen.c 2018-09-14 13:12:10.000000000 +0200 +++ gcc/tree-ssa-strlen.c 2018-09-15 08:04:57.011142267 +0200 @@ -1846,11 +1846,13 @@ is_strlen_related_p (tree src, tree len) bool maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt) { + wide_int cntrange[2]; gimple *stmt = gsi_stmt (gsi); if (gimple_no_warning_p (stmt)) return false; - wide_int cntrange[2]; + if (current_pass && !strcmp (current_pass->name, "ccp")) + return false; if (TREE_CODE (cnt) == INTEGER_CST) cntrange[0] = cntrange[1] = wi::to_wide (cnt); diff -Npur gcc/testsuite/gcc.dg/Wstringop-truncation-6.c gcc/testsuite/gcc.dg/Wstringop-truncation-6.c --- gcc/testsuite/gcc.dg/Wstringop-truncation-6.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc/testsuite/gcc.dg/Wstringop-truncation-6.c 2018-09-15 08:02:35.597198845 +0200 @@ -0,0 +1,59 @@ +/* PR tree-optimization/84561 - -Wstringop-truncation with -O2 depends + on strncpy's size type + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +typedef __SIZE_TYPE__ size_t; + +enum { N = 3 }; + +struct S +{ + char a[N + 1]; +}; + +void set (struct S *ps, const char* s, size_t n) +{ + if (n > N) + n = N; + + __builtin_strncpy (ps->a, s, n); /* { dg-bogus "\\\[-Wstringop-truncation]" } */ + ps->a[n] = 0; +} + +struct A +{ + struct S str; +}; + +void setStringSize_t (struct A *pa, const char *s, size_t n) +{ + set (&pa->str, s, n); +} + +void setStringUnsignedInt (struct A *pa, const char* s, unsigned int n) +{ + set (&pa->str, s, n); +} + +struct B +{ + struct A a; +}; + +struct A* getA (struct B *pb) +{ + return &pb->a; +} + +void f (struct A *pa) +{ + setStringUnsignedInt (pa, "123", N); // No warning here. + setStringSize_t (pa, "123", N); // No warning here. +} + +void g (struct B *pb) +{ + setStringUnsignedInt (getA (pb), "123", N); // Unexpected warning here. + setStringSize_t (getA (pb), "123", N); // No warning here. +}