From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 91059 invoked by alias); 9 Mar 2018 00:47:03 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 91044 invoked by uid 89); 9 Mar 2018 00:47:03 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.7 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,GIT_PATCH_2,GIT_PATCH_3,KAM_ASCII_DIVIDERS,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy=7097 X-HELO: mail-ot0-f194.google.com Received: from mail-ot0-f194.google.com (HELO mail-ot0-f194.google.com) (74.125.82.194) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 09 Mar 2018 00:46:59 +0000 Received: by mail-ot0-f194.google.com with SMTP id 95so7245802ote.5 for ; Thu, 08 Mar 2018 16:46:59 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to; bh=EFDd4ysg+n9pPlcT0FC4dRNcWVBWSkyYa5HUFKiM8J8=; b=jOyRvP1wTkS+UW72rWa1fxzqWi3tRCNlQlaRoDSJ20K/X04gw+XRSvuBRKpy5UQ1Wl IbD1d/pCYxkkAPzhQw5COLFlgipEOmINVhn0Jnq/tJxvJ3+MjKvegVuQQ+29iPvn3NVw jNdVufMAczZcdRkx2sylpy/HuaX1O3fhEb2d2x+w5k/x5veWt9TfjOahqpe/jrhxUxAM IS9mMkhhgMQ7uNoSIzx/gsn9ZtySciYOkRDqZcvtx1f3Q7lolDltvxyDmUiJhzsVONTz aGtbKbTTLOfwKelmOcACpCj/KL4nwLJYEGfCfT65WjCB4rjgZ5XOUhojt1JQufanZLgk wSpQ== X-Gm-Message-State: APf1xPDJVAdDj9CBSxP3kd1vo6LgvhH6UMT5iSySqg9JwmPigvSl4M0L 4orcVvxTLskoALNUlZBYTQQf0Q== X-Google-Smtp-Source: AG47ELunct2HgSU2N2Ff6t/Ub5++CChXN46aUS2GRUwfMsH+SMZ9Bik4D2ubgNhox65UJkjephJfTQ== X-Received: by 10.157.49.84 with SMTP id v20mr20905948otd.103.1520556417409; Thu, 08 Mar 2018 16:46:57 -0800 (PST) Received: from localhost.localdomain (71-218-18-146.hlrn.qwest.net. [71.218.18.146]) by smtp.gmail.com with ESMTPSA id y18sm2229258oix.41.2018.03.08.16.46.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 08 Mar 2018 16:46:56 -0800 (PST) Subject: Re: [PATCH] avoid warning for memcpy to self (PR 83456) To: Richard Biener References: <2db2b46a-b716-4a3c-1e42-a066e40d85c7@gmail.com> Cc: Gcc Patch List From: Martin Sebor Message-ID: <16d23c8e-93df-a765-0128-b1d3a9f4e578@gmail.com> Date: Fri, 09 Mar 2018 00:47:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/mixed; boundary="------------019EF9084A913384C48E222B" X-IsSubscribed: yes X-SW-Source: 2018-03/txt/msg00410.txt.bz2 This is a multi-part message in MIME format. --------------019EF9084A913384C48E222B Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-length: 2100 On 03/08/2018 01:59 AM, Richard Biener wrote: > On Thu, Mar 8, 2018 at 12:01 AM, Martin Sebor wrote: >> 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. > > Ok. I'm sorry, I just discovered that simply removing the code from gimple-fold would cause a regression with respect to GCC 7.0 which does diagnose memcpy(p, p, N) calls, and the diagnostic is useful to users (pr60256 and pr65452 request one for all string functions, although for reasons other than to detect overlapping accesses). To maintain the warning and at the same time eliminate the pesky false positives from gimple-fold I've partially restored the detection in the front-end. That in turn exposed some missing checking of the no-warning bit, leading to duplicate warnings. I've fixed all that up in the attached slightly bigger patch. Martin PS Even with the change to the front end above, removing the memcpy warning from gimple-fold has the downside of failing to detect bugs like: struct S { char a[32]; } s; memcpy (&s, s.a, sizeof s.a); because the front end doesn't know that &s and s.a are at the same address (copying between distinct members of the same union causes another false negative). I want to revisit this in stage 1 and see about handling it. If you have suggestions/preference for how or where I'd appreciate your input. --------------019EF9084A913384C48E222B Content-Type: text/x-patch; name="gcc-83456.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="gcc-83456.diff" Content-length: 22410 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. Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 258366) +++ gcc/c-family/c-common.c (working copy) @@ -5309,10 +5309,11 @@ check_function_sentinel (const_tree fntype, int na } } -/* Check that the same argument isn't passed to restrict arguments - and other arguments. */ +/* Check that the same argument isn't passed to two or more + restrict-qualified formal and issue a -Wrestrict warning + if it is. Return true if a warning has been issued. */ -static void +static bool check_function_restrict (const_tree fndecl, const_tree fntype, int nargs, tree *argarray) { @@ -5322,11 +5323,14 @@ check_function_restrict (const_tree fndecl, const_ if (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL) { - /* Skip checking built-ins here. They are checked in more - detail elsewhere. */ + /* Avoid diagnosing calls built-ins with a zero size/bound + here. They are checked in more detail elsewhere. */ if (DECL_BUILT_IN (fndecl) - && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) - return; + && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL + && nargs == 3 + && TREE_CODE (argarray[2]) == INTEGER_CST + && integer_zerop (argarray[2])) + return false; if (DECL_ARGUMENTS (fndecl)) parms = DECL_ARGUMENTS (fndecl); @@ -5335,6 +5339,8 @@ check_function_restrict (const_tree fndecl, const_ for (i = 0; i < nargs; i++) TREE_VISITED (argarray[i]) = 0; + bool warned = false; + for (i = 0; i < nargs && parms && parms != void_list_node; i++) { tree type; @@ -5351,11 +5357,13 @@ check_function_restrict (const_tree fndecl, const_ if (POINTER_TYPE_P (type) && TYPE_RESTRICT (type) && !TYPE_READONLY (TREE_TYPE (type))) - warn_for_restrict (i, argarray, nargs); + warned |= warn_for_restrict (i, argarray, nargs); } for (i = 0; i < nargs; i++) TREE_VISITED (argarray[i]) = 0; + + return warned; } /* Helper for check_function_nonnull; given a list of operands which @@ -5596,8 +5604,10 @@ attribute_fallthrough_p (tree attr) /* Check for valid arguments being passed to a function with FNTYPE. - There are NARGS arguments in the array ARGARRAY. LOC should be used for - diagnostics. Return true if -Wnonnull warning has been diagnosed. */ + There are NARGS arguments in the array ARGARRAY. LOC should be used + for diagnostics. Return true if either -Wnonnull or -Wrestrict has + been issued. */ + bool check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, int nargs, tree *argarray, vec *arglocs) @@ -5620,7 +5630,7 @@ check_function_arguments (location_t loc, const_tr check_function_sentinel (fntype, nargs, argarray); if (warn_restrict) - check_function_restrict (fndecl, fntype, nargs, argarray); + warned_p |= check_function_restrict (fndecl, fntype, nargs, argarray); return warned_p; } Index: gcc/c-family/c-common.h =================================================================== --- gcc/c-family/c-common.h (revision 258366) +++ gcc/c-family/c-common.h (working copy) @@ -1269,7 +1269,7 @@ extern void warnings_for_convert_and_check (locati extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool, bool); extern void warn_for_omitted_condop (location_t, tree); -extern void warn_for_restrict (unsigned, tree *, unsigned); +extern bool warn_for_restrict (unsigned, tree *, unsigned); /* Places where an lvalue, or modifiable lvalue, may be required. Used to select diagnostic messages in lvalue_error and Index: gcc/c-family/c-warn.c =================================================================== --- gcc/c-family/c-warn.c (revision 258366) +++ gcc/c-family/c-warn.c (working copy) @@ -2372,14 +2372,15 @@ maybe_warn_bool_compare (location_t loc, enum tree } /* Warn if an argument at position param_pos is passed to a - restrict-qualified param, and it aliases with another argument. */ + restrict-qualified param, and it aliases with another argument. + Return true if a warning has been issued. */ -void +bool warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs) { tree arg = argarray[param_pos]; if (TREE_VISITED (arg) || integer_zerop (arg)) - return; + return false; location_t loc = EXPR_LOC_OR_LOC (arg, input_location); gcc_rich_location richloc (loc); @@ -2395,13 +2396,13 @@ warn_for_restrict (unsigned param_pos, tree *argar tree current_arg = argarray[i]; if (operand_equal_p (arg, current_arg, 0)) { - TREE_VISITED (current_arg) = 1; + TREE_VISITED (current_arg) = 1; arg_positions.safe_push (i + 1); } } if (arg_positions.is_empty ()) - return; + return false; int pos; FOR_EACH_VEC_ELT (arg_positions, i, pos) @@ -2411,13 +2412,13 @@ warn_for_restrict (unsigned param_pos, tree *argar richloc.add_range (EXPR_LOCATION (arg), false); } - warning_n (&richloc, OPT_Wrestrict, arg_positions.length (), - "passing argument %i to restrict-qualified parameter" - " aliases with argument %Z", - "passing argument %i to restrict-qualified parameter" - " aliases with arguments %Z", - param_pos + 1, arg_positions.address (), - arg_positions.length ()); + return warning_n (&richloc, OPT_Wrestrict, arg_positions.length (), + "passing argument %i to restrict-qualified parameter" + " aliases with argument %Z", + "passing argument %i to restrict-qualified parameter" + " aliases with arguments %Z", + param_pos + 1, arg_positions.address (), + arg_positions.length ()); } /* Callback function to determine whether an expression TP or one of its Index: gcc/gimple-fold.c =================================================================== --- gcc/gimple-fold.c (revision 258366) +++ gcc/gimple-fold.c (working copy) @@ -682,11 +682,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterato tree destvar, srcvar; location_t loc = gimple_location (stmt); - tree func = gimple_call_fndecl (stmt); bool nowarn = gimple_no_warning_p (stmt); - bool check_overlap = (DECL_FUNCTION_CODE (func) != BUILT_IN_MEMMOVE - && DECL_FUNCTION_CODE (func) != BUILT_IN_MEMMOVE_CHK - && !nowarn); /* If the LEN parameter is a constant zero or in range where the only valid value is zero, return DEST. */ @@ -713,13 +709,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)); @@ -1622,11 +1612,14 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator * /* If SRC and DEST are the same (and not volatile), return DEST. */ if (operand_equal_p (src, dest, 0)) { - tree func = gimple_call_fndecl (stmt); + if (!gimple_no_warning_p (stmt)) + { + tree func = gimple_call_fndecl (stmt); - warning_at (loc, OPT_Wrestrict, - "%qD source argument is the same as destination", - func); + warning_at (loc, OPT_Wrestrict, + "%qD source argument is the same as destination", + func); + } replace_call_with_value (gsi, dest); return true; @@ -2499,15 +2492,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); @@ -2609,11 +2593,14 @@ gimple_fold_builtin_stxcpy_chk (gimple_stmt_iterat /* If SRC and DEST are the same (and not volatile), return DEST. */ if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0)) { - tree func = gimple_call_fndecl (stmt); + if (!gimple_no_warning_p (stmt)) + { + tree func = gimple_call_fndecl (stmt); - warning_at (loc, OPT_Wrestrict, - "%qD source argument is the same as destination", - func); + warning_at (loc, OPT_Wrestrict, + "%qD source argument is the same as destination", + func); + } replace_call_with_value (gsi, dest); return true; Index: gcc/tree-ssa-strlen.c =================================================================== --- gcc/tree-ssa-strlen.c (revision 258366) +++ gcc/tree-ssa-strlen.c (working copy) @@ -1801,6 +1801,8 @@ bool maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt) { gimple *stmt = gsi_stmt (gsi); + if (gimple_no_warning_p (stmt)) + return false; wide_int cntrange[2]; Index: gcc/testsuite/c-c++-common/Wrestrict-2.c =================================================================== --- gcc/testsuite/c-c++-common/Wrestrict-2.c (revision 258366) +++ 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 258366) +++ 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" } */ @@ -447,22 +428,10 @@ void test_memcpy_var (char *d, const char *s) { size_t n = unsigned_value (); + /* Since no copying takes place no warning should be issued. */ 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 +468,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" } */ } @@ -941,7 +906,7 @@ void test_strncpy_range (char *d, size_t n) /* The following overlaps except in the unlikely case that value () is zero, so it's diagnosed. */ - T ("012", a, a, n); /* { dg-warning "source argument is the same as destination " "strncpy" } */ + T ("012", a, a, n); /* { dg-warning "\\\[-Wrestrict]" "strncpy" } */ } 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); +} Index: gcc/testsuite/gcc.dg/Wrestrict-14.c =================================================================== --- gcc/testsuite/gcc.dg/Wrestrict-14.c (nonexistent) +++ gcc/testsuite/gcc.dg/Wrestrict-14.c (working copy) @@ -0,0 +1,221 @@ +/* PR tree-optimization/83456 - -Wrestrict false positive on a non-overlapping + memcpy in an inline function + Verify that calls to built-in functions are diagnosed when the pointer + arguments to their restrict-qualified parameters are the same (the absence + of the false positives reported in PR 83456 is tested in Wrestrict-12.c. + { dg-do compile } + { dg-options "-O2 -Wall -Wrestrict -Wno-stringop-truncation" } */ + +typedef __SIZE_TYPE__ size_t; + +extern void* memcpy (void* restrict, const void* restrict, size_t); +extern void* mempcpy (void* restrict, const void* restrict, size_t); +extern char* stpncpy (char* restrict, const char* restrict, size_t); +extern char* stpcpy (char* restrict, const char* restrict); +extern char* strncat (char* restrict, const char* restrict, size_t); +extern char* strcat (char* restrict, const char* restrict); +extern char* strncpy (char* restrict, const char* restrict, size_t); +extern char* strcpy (char* restrict, const char* restrict); + +struct S +{ + char a[4]; + char *p; +} s; + +void sink (void*); + +void test_memcpy (char *p, struct S *q, size_t n) +{ + /* The behavior of memcpy() is undefined only when when copying takes + place between overlapping objects. Since a call with a size of zero + does nothing, it should not be diagnosed. */ + memcpy (p, p, 0); + sink (p); + + memcpy (p, p, 1); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + memcpy (p, p, n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + memcpy (q->a, q->a, 0); + sink (q); + + memcpy (q->p, q->p, 1); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + memcpy (&q->a[0], q->a, n); /* { dg-warning "\\\[-Wrestrict]" "bug ????" { xfail *-*-* } } */ + sink (q); + + memcpy (q, q->a, n); /* { dg-warning "\\\[-Wrestrict]" "bug ????" { xfail *-*-* } } */ + sink (q); +} + +void test_mempcpy (char *p, struct S *q, size_t n) +{ + mempcpy (p, p, 0); + sink (p); + + mempcpy (p, p, 1); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + mempcpy (p, p, n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + mempcpy (q->a, q->a, 0); + sink (q); + + mempcpy (q->p, q->p, 1); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + mempcpy (&q->a[0], q->a, n); /* { dg-warning "\\\[-Wrestrict]" "bug ????" { xfail *-*-* } } */ + sink (q); + + mempcpy (q, q->a, n); /* { dg-warning "\\\[-Wrestrict]" "bug ????" { xfail *-*-* } } */ + sink (q); +} + +void test_strncat (char *p, struct S *q, size_t n) +{ + strncat (p, p, 0); + sink (p); + + strncat (p, p, 1); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + strncat (p, p, n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + strncat (q->a, q->a, n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strncat (&q->a[0], &q->a[0], n);/* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strncat (q->a, &q->a[0], n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strncat (q->p, &q->p[0], n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); +} + +void test_strcat (char *p, struct S *q, size_t n) +{ + strcat (p, p); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + strcat (p, p); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + strcat (p, p); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + strcat (q->a, q->a); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strcat (&q->a[0], &q->a[0]); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strcat (q->a, &q->a[0]); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strcat (q->p, &q->p[0]); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); +} + +void test_stpncpy (char *p, struct S *q, size_t n) +{ + stpncpy (p, p, 0); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + stpncpy (p, p, 1); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + stpncpy (p, p, n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + stpncpy (q->a, q->a, n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + stpncpy (&q->a[0], &q->a[0], n);/* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + stpncpy (q->a, &q->a[0], n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + stpncpy (q->p, &q->p[0], n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); +} + +void test_stpcpy (char *p, struct S *q, size_t n) +{ + stpcpy (p, p); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + stpcpy (p, p); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + stpcpy (p, p); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + stpcpy (q->a, q->a); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + stpcpy (&q->a[0], &q->a[0]); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + stpcpy (q->a, &q->a[0]); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + stpcpy (q->p, &q->p[0]); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); +} + +void test_strncpy (char *p, struct S *q, size_t n) +{ + strncpy (p, p, 0); + sink (p); + + strncpy (p, p, 1); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + strncpy (p, p, n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + strncpy (q->a, q->a, n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strncpy (&q->a[0], &q->a[0], n);/* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strncpy (q->a, &q->a[0], n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strncpy (q->p, &q->p[0], n); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); +} + +void test_strcpy (char *p, struct S *q, size_t n) +{ + strcpy (p, p); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + strcpy (p, p); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + strcpy (p, p); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (p); + + strcpy (q->a, q->a); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strcpy (&q->a[0], &q->a[0]); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strcpy (q->a, &q->a[0]); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); + + strcpy (q->p, &q->p[0]); /* { dg-warning "\\\[-Wrestrict]" } */ + sink (q); +} --------------019EF9084A913384C48E222B--