From 75e9093e0068dde034aca984805fc31cd78eacb6 Mon Sep 17 00:00:00 2001 From: msebor Date: Mon, 12 Mar 2018 18:04:16 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@258455 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 10 ++ gcc/c-family/ChangeLog | 10 ++ gcc/c-family/c-common.c | 32 +++-- gcc/c-family/c-common.h | 2 +- gcc/c-family/c-warn.c | 25 ++-- gcc/gimple-fold.c | 43 +++--- gcc/testsuite/ChangeLog | 15 +++ gcc/testsuite/c-c++-common/Wrestrict-2.c | 8 +- gcc/testsuite/c-c++-common/Wrestrict.c | 39 +----- gcc/testsuite/gcc.dg/Wrestrict-12.c | 66 +++++++++ gcc/testsuite/gcc.dg/Wrestrict-14.c | 221 +++++++++++++++++++++++++++++++ gcc/tree-ssa-strlen.c | 2 + 12 files changed, 380 insertions(+), 93 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/Wrestrict-12.c create mode 100644 gcc/testsuite/gcc.dg/Wrestrict-14.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f9f986bfab5..bc771c64a61 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2018-03-12 Martin Sebor + + 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. + 2018-03-12 Segher Boessenkool * config/rs6000/rs6000.c (abi_v4_pass_in_fpr): Add bool "named" diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index fe1fc81139e..259445365c4 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,13 @@ +2018-03-12 Martin Sebor + + 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. + 2018-03-02 Marek Polacek PR c++/84171 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 858ed68f2d1..e1df1d3b73b 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -5309,10 +5309,11 @@ check_function_sentinel (const_tree fntype, int nargs, tree *argarray) } } -/* 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_tree fntype, 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_tree fntype, 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_tree fntype, 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_tree fndecl, const_tree fntype, 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; } diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 95bb0fd2b06..6cf7614f682 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1269,7 +1269,7 @@ extern void warnings_for_convert_and_check (location_t, tree, tree, tree); 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 diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 7c385959c4f..51c376b7c37 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -2372,14 +2372,15 @@ maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0, } /* 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 *argarray, unsigned nargs) 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 *argarray, unsigned nargs) 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 diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 8257873dd20..7771988b837 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -682,11 +682,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi, 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_iterator *gsi, { /* 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 *gsi, /* 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_iterator *gsi, (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_iterator *gsi, /* 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5dead01586c..a5e3408c4c4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2018-03-12 Martin Sebor + + 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 + } + } + 2018-03-12 H.J. Lu * g++.dg/pr84821.C: New test. diff --git a/gcc/testsuite/c-c++-common/Wrestrict-2.c b/gcc/testsuite/c-c++-common/Wrestrict-2.c index 2c10eeffb51..c3e9ac82d64 100644 --- a/gcc/testsuite/c-c++-common/Wrestrict-2.c +++ b/gcc/testsuite/c-c++-common/Wrestrict-2.c @@ -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); } diff --git a/gcc/testsuite/c-c++-common/Wrestrict.c b/gcc/testsuite/c-c++-common/Wrestrict.c index e62652f78e1..36a1ffa412c 100644 --- a/gcc/testsuite/c-c++-common/Wrestrict.c +++ b/gcc/testsuite/c-c++-common/Wrestrict.c @@ -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" } */ } diff --git a/gcc/testsuite/gcc.dg/Wrestrict-12.c b/gcc/testsuite/gcc.dg/Wrestrict-12.c new file mode 100644 index 00000000000..84ab6b50d8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wrestrict-12.c @@ -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); +} diff --git a/gcc/testsuite/gcc.dg/Wrestrict-14.c b/gcc/testsuite/gcc.dg/Wrestrict-14.c new file mode 100644 index 00000000000..b919fa644d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wrestrict-14.c @@ -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); +} diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 72f6a17cd32..33004b6870d 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -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]; -- 2.11.4.GIT