Bug 83456 - -Wrestrict false positive on a non-overlapping memcpy in an inline function
Summary: -Wrestrict false positive on a non-overlapping memcpy in an inline function
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 8.0
: P3 normal
Target Milestone: ---
Assignee: Martin Sebor
URL:
Keywords: diagnostic, patch
Depends on:
Blocks: Wrestrict
  Show dependency treegraph
 
Reported: 2017-12-17 23:04 UTC by Martin Sebor
Modified: 2020-01-31 00:45 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2018-02-06 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2017-12-17 23:04:12 UTC
As reported in bug 78918, comment #7, the enhanced -Wrestrict warning issues a false positive on the following code.  The false positive is caused by issuing the warning during folding, after bar() has been inlined but before the call to memcpy has been eliminated.  The reason for issuing the warning in this case (i.e., equal operands) is to help detect bugs in code built without optimization when an unguarded overlapping call to the library function would be made, but it may not be worth the bug reports for the safe cases like this one.

$ cat z.c && gcc -O2 -S -Wall z.c
extern void* memcpy (void*, const void*, __SIZE_TYPE__);

inline void bar (void *d, void *s, unsigned N)
{
  if (s != d)
    memcpy (d, s, N);
}

void foo (void* src)
{
  bar (src, src, 1);
}
z.c: In function ‘foo’:
z.c:6:5: warning: ‘memcpy’ source argument is the same as destination [-Wrestrict]
     memcpy (d, s, N);
     ^~~~~~~~~~~~~~~~
Comment 1 Martin Sebor 2018-02-06 18:39:44 UTC
Here's a slightly different test case, this one from bug 84095 comment 14 (reduced from bug 84095 comment 17).  I'll confirm this bug based on that one.

$ cat t.c && gcc -O2 -S -Wall t.c
extern void* memcpy (void*, const void*, __SIZE_TYPE__);

char a[4];

void f (unsigned n)
{
  for (int i = 0; i < 1; i++)
    {
      if (!i)
	continue;

      memcpy (a, a, n);
    }
}
t.c: In function ‘f’:
t.c:12:7: warning: ‘memcpy’ source argument is the same as destination [-Wrestrict]
       memcpy (a, a, n);
       ^~~~~~~~~~~~~~~~
Comment 2 Martin Sebor 2018-02-06 18:53:18 UTC
And another test case from bug 84095 comment #9, also due to the check in gimple-fold.c.  This one seems closer to the first test case in comment #0. 

$ cat t.c && gcc -O2 -S -Wall t.c
extern void* memcpy (void*, const void*, __SIZE_TYPE__);

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);
}
t.c: In function ‘sit_init_net’:
t.c:23:3: warning: ‘memcpy’ source argument is the same as destination [-Wrestrict]
   memcpy(&t->ip6rd, &t0->ip6rd, sizeof(t->ip6rd));
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comment 3 Martin Sebor 2018-02-06 19:03:08 UTC
See also bug 32667 for some background into GCC emitting perfectly overlapping calls to memcpy for some aggregate assignments.  The code that controls the diagnostic tries to work around that bug:

  /* If SRC and DEST are the same (and not volatile), return
     DEST{,+LEN,+LEN-1}.  */
  if (operand_equal_p (src, dest, 0))
    {
      /* 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);
Comment 4 Martin Sebor 2018-03-07 23:02:58 UTC
Patch: https://gcc.gnu.org/ml/gcc-patches/2018-03/msg00358.html
Comment 5 Martin Sebor 2018-03-12 18:04:47 UTC
Author: msebor
Date: Mon Mar 12 18:04:16 2018
New Revision: 258455

URL: https://gcc.gnu.org/viewcvs?rev=258455&root=gcc&view=rev
Log:
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.
	(gimple_fold_builtin_strcpy): Handle no-warning.
	(gimple_fold_builtin_stxcpy_chk): Same.
	* tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Handle no-warning.

gcc/c-family/ChangeLog:

	PR tree-optimization/83456
	* gcc/c-family/c-common.c (check_function_restrict): Return bool.
	Restore checking of bounded built-in functions.
	(check_function_arguments): Also return the result
	of warn_for_restrict.
	* gcc/c-family/c-common.c (check_function_restrict): Return bool.
	* gcc/c-family/c-warn.c (warn_for_restrict): Return bool.

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.
	* gcc.dg/Wrestrict-14.c: New test.

Added:
    trunk/gcc/testsuite/gcc.dg/Wrestrict-12.c
    trunk/gcc/testsuite/gcc.dg/Wrestrict-14.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/c-family/ChangeLog
    trunk/gcc/c-family/c-common.c
    trunk/gcc/c-family/c-common.h
    trunk/gcc/c-family/c-warn.c
    trunk/gcc/gimple-fold.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/c-c++-common/Wrestrict-2.c
    trunk/gcc/testsuite/c-c++-common/Wrestrict.c
    trunk/gcc/tree-ssa-strlen.c
Comment 6 Martin Sebor 2018-03-12 18:05:16 UTC
Patch committed in r258455.