This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] avoid warning for memcpy to self (PR 83456)
- From: Martin Sebor <msebor at gmail dot com>
- To: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 7 Mar 2018 16:01:42 -0700
- Subject: [PATCH] avoid warning for memcpy to self (PR 83456)
- Authentication-results: sourceware.org; auth=none
I have become convinced that issuing -Wrestrict in gimple-fold
for calls to memcpy() where the source pointer is the same as
the destination causes more trouble than it's worth, especially
when inlining is involved, as in:
inline void bar (void *d, void *s, unsigned N)
{
if (s != d)
memcpy (d, s, N);
}
void foo (void* src)
{
bar (src, src, 1);
}
It seems that there should be a way to teach GCC to avoid
folding statements in dead blocks (e.g., in a block controlled
by 'if (0 != 0)' as the one below), and that it might even speed
up compilation, but in the meantime it leads to false positive
-Wrestrict warnings.
The attached patch removes this instance of the warning and
adjusts tests not to expect it.
Martin
PR tree-optimization/83456 - -Wrestrict false positive on a non-overlapping memcpy in an inline function
gcc/ChangeLog:
PR tree-optimization/83456
* gimple-fold.c (gimple_fold_builtin_memory_op): Avoid warning
for perfectly overlapping calls to memcpy.
(gimple_fold_builtin_memory_chk): Same.
gcc/testsuite/ChangeLog:
PR tree-optimization/83456
* c-c++-common/Wrestrict-2.c: Remove test cases.
* c-c++-common/Wrestrict.c: Same.
* gcc.dg/Wrestrict-12.c: New test.
Index: gcc/gimple-fold.c
===================================================================
--- gcc/gimple-fold.c (revision 258339)
+++ gcc/gimple-fold.c (working copy)
@@ -713,13 +713,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterato
{
/* Avoid diagnosing exact overlap in calls to __builtin_memcpy.
It's safe and may even be emitted by GCC itself (see bug
- 32667). However, diagnose it in explicit calls to the memcpy
- function. */
- if (check_overlap && *IDENTIFIER_POINTER (DECL_NAME (func)) != '_')
- warning_at (loc, OPT_Wrestrict,
- "%qD source argument is the same as destination",
- func);
-
+ 32667). */
unlink_stmt_vdef (stmt);
if (gimple_vdef (stmt) && TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
release_ssa_name (gimple_vdef (stmt));
@@ -2499,15 +2493,6 @@ gimple_fold_builtin_memory_chk (gimple_stmt_iterat
(resp. DEST+LEN for __mempcpy_chk). */
if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
{
- if (fcode != BUILT_IN_MEMMOVE && fcode != BUILT_IN_MEMMOVE_CHK)
- {
- tree func = gimple_call_fndecl (stmt);
-
- warning_at (loc, OPT_Wrestrict,
- "%qD source argument is the same as destination",
- func);
- }
-
if (fcode != BUILT_IN_MEMPCPY_CHK)
{
replace_call_with_value (gsi, dest);
Index: gcc/testsuite/c-c++-common/Wrestrict-2.c
===================================================================
--- gcc/testsuite/c-c++-common/Wrestrict-2.c (revision 258339)
+++ gcc/testsuite/c-c++-common/Wrestrict-2.c (working copy)
@@ -12,13 +12,13 @@
static void wrap_memcpy (void *d, const void *s, size_t n)
{
- memcpy (d, s, n); /* { dg-warning "source argument is the same as destination" "memcpy" } */
+ memcpy (d, s, n); /* { dg-warning "accessing 2 bytes at offsets 0 and 1 overlaps 1 byte at offset 1" "memcpy" } */
}
-void call_memcpy (void *d, size_t n)
+void call_memcpy (char *d)
{
- const void *s = d;
- wrap_memcpy (d, s, n);
+ const void *s = d + 1;
+ wrap_memcpy (d, s, 2);
}
Index: gcc/testsuite/c-c++-common/Wrestrict.c
===================================================================
--- gcc/testsuite/c-c++-common/Wrestrict.c (revision 258339)
+++ gcc/testsuite/c-c++-common/Wrestrict.c (working copy)
@@ -52,7 +52,6 @@ void test_memcpy_cst (void *d, const void *s)
} while (0)
T (a, a, 0);
- T (a, s = a, 3); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
/* This isn't detected because memcpy calls with small power-of-2 sizes
are intentionally folded into safe copies equivalent to memmove.
@@ -64,19 +63,6 @@ void test_memcpy_cst (void *d, const void *s)
T (a, a + 3, 5); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
{
- char a[3] = { 1, 2, 3 };
-
- /* Verify that a call to memcpy with an exact overlap is diagnosed
- (also tested above) but an excplicit one to __builtin_memcpy is
- not. See bug 32667 for the rationale. */
- (memcpy)(a, a, sizeof a); /* { dg-warning "source argument is the same as destination" "memcpy" } */
- sink (a);
-
- __builtin_memcpy (a, a, sizeof a);
- sink (a);
- }
-
- {
char a[3][7];
sink (a);
@@ -116,11 +102,6 @@ void test_memcpy_cst (void *d, const void *s)
memcpy (d, s, sizeof x.a);
sink (&x);
- d = x.a;
- s = x.a;
- memcpy (d, s, sizeof x.a); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
- sink (&x);
-
d = x.a + 4;
s = x.b;
memcpy (d, s, sizeof x.a); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
@@ -450,19 +431,6 @@ void test_memcpy_var (char *d, const char *s)
memcpy (d, d, 0);
sink (d);
- memcpy (d, d, n); /* { dg-warning "source argument is the same as destination" "memcpy" } */
- sink (d);
-
- memcpy (d, &d[0], n); /* { dg-warning "source argument is the same as destination" "memcpy" } */
- sink (d);
-
- memcpy (&d[0], d, n); /* { dg-warning "source argument is the same as destination" "memcpy" } */
- sink (d);
-
- s = d;
- memcpy (d, s, n); /* { dg-warning "source argument is the same as destination" "memcpy" } */
- sink (d);
-
/* The following overlaps if n is greater than 1. */
s = d + 1;
memcpy (d, s, n);
@@ -499,10 +467,6 @@ void test_memcpy_var (char *d, const char *s)
s = d + 5;
n = 7;
memcpy (d, s, n); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
-
- n = UR (0, 1);
- s = d;
- memcpy (d, s, n); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
}
Index: gcc/testsuite/gcc.dg/Wrestrict-12.c
===================================================================
--- gcc/testsuite/gcc.dg/Wrestrict-12.c (nonexistent)
+++ gcc/testsuite/gcc.dg/Wrestrict-12.c (working copy)
@@ -0,0 +1,66 @@
+/* PR tree-optimization/83456 - -Wrestrict false positive on
+ a non-overlapping memcpy in an inline function
+ { dg-do compile }
+ { dg-options "-O2 -Wrestrict -ftrack-macro-expansion=0" } */
+
+extern void* memcpy (void*, const void*, __SIZE_TYPE__);
+
+/* Test case from comment #0. */
+
+inline void pr83456_comment0 (void *d, void *s, unsigned N)
+{
+ if (s != d)
+ memcpy (d, s, N);
+}
+
+void call_pr83456_comment0 (void* src)
+{
+ pr83456_comment0 (src, src, 1);
+}
+
+
+/* Test case from comment #1. */
+
+char a[4];
+
+void pr83456_comment1 (unsigned n)
+{
+ for (int i = 0; i < 1; i++)
+ {
+ if (!i)
+ continue;
+
+ memcpy (a, a, n);
+ }
+}
+
+/* Test case from comment #2. */
+
+struct netdevice {
+ void *priv;
+};
+
+struct ip_tunnel {
+ struct netdevice *dev;
+ int ip6rd[3];
+};
+
+struct sit_net {
+ struct netdevice *fb_tunnel_dev;
+};
+
+void ipip6_tunnel_clone_6rd (struct netdevice *dev, struct sit_net *sitn)
+{
+ struct ip_tunnel *t = dev->priv;
+ if (t->dev == sitn->fb_tunnel_dev)
+ return;
+
+ struct ip_tunnel *t0 = sitn->fb_tunnel_dev->priv;
+ memcpy(&t->ip6rd, &t0->ip6rd, sizeof(t->ip6rd));
+}
+
+void sit_init_net (struct sit_net *sitn, struct netdevice *fb_tunnel_dev)
+{
+ sitn->fb_tunnel_dev = fb_tunnel_dev;
+ ipip6_tunnel_clone_6rd (sitn->fb_tunnel_dev, sitn);
+}