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.
+}

Reply via email to