Commit e9b9fa4c by Martin Sebor Committed by Martin Sebor

PR tree-optimization/83456 - -Wrestrict false positive on a non-overlapping…

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.

From-SVN: r258455
parent df4cfec5
2018-03-12 Martin Sebor <msebor@redhat.com>
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 <segher@kernel.crashing.org> 2018-03-12 Segher Boessenkool <segher@kernel.crashing.org>
* config/rs6000/rs6000.c (abi_v4_pass_in_fpr): Add bool "named" * config/rs6000/rs6000.c (abi_v4_pass_in_fpr): Add bool "named"
......
2018-03-12 Martin Sebor <msebor@redhat.com>
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 <polacek@redhat.com> 2018-03-02 Marek Polacek <polacek@redhat.com>
PR c++/84171 PR c++/84171
......
...@@ -5309,10 +5309,11 @@ check_function_sentinel (const_tree fntype, int nargs, tree *argarray) ...@@ -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 /* Check that the same argument isn't passed to two or more
and other arguments. */ 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, check_function_restrict (const_tree fndecl, const_tree fntype,
int nargs, tree *argarray) int nargs, tree *argarray)
{ {
...@@ -5322,11 +5323,14 @@ check_function_restrict (const_tree fndecl, const_tree fntype, ...@@ -5322,11 +5323,14 @@ check_function_restrict (const_tree fndecl, const_tree fntype,
if (fndecl if (fndecl
&& TREE_CODE (fndecl) == FUNCTION_DECL) && TREE_CODE (fndecl) == FUNCTION_DECL)
{ {
/* Skip checking built-ins here. They are checked in more /* Avoid diagnosing calls built-ins with a zero size/bound
detail elsewhere. */ here. They are checked in more detail elsewhere. */
if (DECL_BUILT_IN (fndecl) if (DECL_BUILT_IN (fndecl)
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
return; && nargs == 3
&& TREE_CODE (argarray[2]) == INTEGER_CST
&& integer_zerop (argarray[2]))
return false;
if (DECL_ARGUMENTS (fndecl)) if (DECL_ARGUMENTS (fndecl))
parms = DECL_ARGUMENTS (fndecl); parms = DECL_ARGUMENTS (fndecl);
...@@ -5335,6 +5339,8 @@ check_function_restrict (const_tree fndecl, const_tree fntype, ...@@ -5335,6 +5339,8 @@ check_function_restrict (const_tree fndecl, const_tree fntype,
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
TREE_VISITED (argarray[i]) = 0; TREE_VISITED (argarray[i]) = 0;
bool warned = false;
for (i = 0; i < nargs && parms && parms != void_list_node; i++) for (i = 0; i < nargs && parms && parms != void_list_node; i++)
{ {
tree type; tree type;
...@@ -5351,11 +5357,13 @@ check_function_restrict (const_tree fndecl, const_tree fntype, ...@@ -5351,11 +5357,13 @@ check_function_restrict (const_tree fndecl, const_tree fntype,
if (POINTER_TYPE_P (type) if (POINTER_TYPE_P (type)
&& TYPE_RESTRICT (type) && TYPE_RESTRICT (type)
&& !TYPE_READONLY (TREE_TYPE (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++) for (i = 0; i < nargs; i++)
TREE_VISITED (argarray[i]) = 0; TREE_VISITED (argarray[i]) = 0;
return warned;
} }
/* Helper for check_function_nonnull; given a list of operands which /* Helper for check_function_nonnull; given a list of operands which
...@@ -5596,8 +5604,10 @@ attribute_fallthrough_p (tree attr) ...@@ -5596,8 +5604,10 @@ attribute_fallthrough_p (tree attr)
/* Check for valid arguments being passed to a function with FNTYPE. /* Check for valid arguments being passed to a function with FNTYPE.
There are NARGS arguments in the array ARGARRAY. LOC should be used for There are NARGS arguments in the array ARGARRAY. LOC should be used
diagnostics. Return true if -Wnonnull warning has been diagnosed. */ for diagnostics. Return true if either -Wnonnull or -Wrestrict has
been issued. */
bool bool
check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype,
int nargs, tree *argarray, vec<location_t> *arglocs) int nargs, tree *argarray, vec<location_t> *arglocs)
...@@ -5620,7 +5630,7 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, ...@@ -5620,7 +5630,7 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype,
check_function_sentinel (fntype, nargs, argarray); check_function_sentinel (fntype, nargs, argarray);
if (warn_restrict) if (warn_restrict)
check_function_restrict (fndecl, fntype, nargs, argarray); warned_p |= check_function_restrict (fndecl, fntype, nargs, argarray);
return warned_p; return warned_p;
} }
......
...@@ -1269,7 +1269,7 @@ extern void warnings_for_convert_and_check (location_t, tree, tree, tree); ...@@ -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, extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool,
bool); bool);
extern void warn_for_omitted_condop (location_t, tree); 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. /* Places where an lvalue, or modifiable lvalue, may be required.
Used to select diagnostic messages in lvalue_error and Used to select diagnostic messages in lvalue_error and
......
...@@ -2372,14 +2372,15 @@ maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0, ...@@ -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 /* 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) warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
{ {
tree arg = argarray[param_pos]; tree arg = argarray[param_pos];
if (TREE_VISITED (arg) || integer_zerop (arg)) if (TREE_VISITED (arg) || integer_zerop (arg))
return; return false;
location_t loc = EXPR_LOC_OR_LOC (arg, input_location); location_t loc = EXPR_LOC_OR_LOC (arg, input_location);
gcc_rich_location richloc (loc); gcc_rich_location richloc (loc);
...@@ -2395,13 +2396,13 @@ warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs) ...@@ -2395,13 +2396,13 @@ warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
tree current_arg = argarray[i]; tree current_arg = argarray[i];
if (operand_equal_p (arg, current_arg, 0)) if (operand_equal_p (arg, current_arg, 0))
{ {
TREE_VISITED (current_arg) = 1; TREE_VISITED (current_arg) = 1;
arg_positions.safe_push (i + 1); arg_positions.safe_push (i + 1);
} }
} }
if (arg_positions.is_empty ()) if (arg_positions.is_empty ())
return; return false;
int pos; int pos;
FOR_EACH_VEC_ELT (arg_positions, i, pos) FOR_EACH_VEC_ELT (arg_positions, i, pos)
...@@ -2411,13 +2412,13 @@ warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs) ...@@ -2411,13 +2412,13 @@ warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
richloc.add_range (EXPR_LOCATION (arg), false); richloc.add_range (EXPR_LOCATION (arg), false);
} }
warning_n (&richloc, OPT_Wrestrict, arg_positions.length (), return warning_n (&richloc, OPT_Wrestrict, arg_positions.length (),
"passing argument %i to restrict-qualified parameter" "passing argument %i to restrict-qualified parameter"
" aliases with argument %Z", " aliases with argument %Z",
"passing argument %i to restrict-qualified parameter" "passing argument %i to restrict-qualified parameter"
" aliases with arguments %Z", " aliases with arguments %Z",
param_pos + 1, arg_positions.address (), param_pos + 1, arg_positions.address (),
arg_positions.length ()); arg_positions.length ());
} }
/* Callback function to determine whether an expression TP or one of its /* Callback function to determine whether an expression TP or one of its
......
...@@ -682,11 +682,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi, ...@@ -682,11 +682,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
tree destvar, srcvar; tree destvar, srcvar;
location_t loc = gimple_location (stmt); location_t loc = gimple_location (stmt);
tree func = gimple_call_fndecl (stmt);
bool nowarn = gimple_no_warning_p (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 /* If the LEN parameter is a constant zero or in range where
the only valid value is zero, return DEST. */ the only valid value is zero, return DEST. */
...@@ -713,13 +709,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi, ...@@ -713,13 +709,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
{ {
/* Avoid diagnosing exact overlap in calls to __builtin_memcpy. /* Avoid diagnosing exact overlap in calls to __builtin_memcpy.
It's safe and may even be emitted by GCC itself (see bug It's safe and may even be emitted by GCC itself (see bug
32667). However, diagnose it in explicit calls to the memcpy 32667). */
function. */
if (check_overlap && *IDENTIFIER_POINTER (DECL_NAME (func)) != '_')
warning_at (loc, OPT_Wrestrict,
"%qD source argument is the same as destination",
func);
unlink_stmt_vdef (stmt); unlink_stmt_vdef (stmt);
if (gimple_vdef (stmt) && TREE_CODE (gimple_vdef (stmt)) == SSA_NAME) if (gimple_vdef (stmt) && TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
release_ssa_name (gimple_vdef (stmt)); release_ssa_name (gimple_vdef (stmt));
...@@ -1622,11 +1612,14 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi, ...@@ -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 SRC and DEST are the same (and not volatile), return DEST. */
if (operand_equal_p (src, dest, 0)) 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, warning_at (loc, OPT_Wrestrict,
"%qD source argument is the same as destination", "%qD source argument is the same as destination",
func); func);
}
replace_call_with_value (gsi, dest); replace_call_with_value (gsi, dest);
return true; return true;
...@@ -2499,15 +2492,6 @@ gimple_fold_builtin_memory_chk (gimple_stmt_iterator *gsi, ...@@ -2499,15 +2492,6 @@ gimple_fold_builtin_memory_chk (gimple_stmt_iterator *gsi,
(resp. DEST+LEN for __mempcpy_chk). */ (resp. DEST+LEN for __mempcpy_chk). */
if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0)) 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) if (fcode != BUILT_IN_MEMPCPY_CHK)
{ {
replace_call_with_value (gsi, dest); replace_call_with_value (gsi, dest);
...@@ -2609,11 +2593,14 @@ gimple_fold_builtin_stxcpy_chk (gimple_stmt_iterator *gsi, ...@@ -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 SRC and DEST are the same (and not volatile), return DEST. */
if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0)) 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, warning_at (loc, OPT_Wrestrict,
"%qD source argument is the same as destination", "%qD source argument is the same as destination",
func); func);
}
replace_call_with_value (gsi, dest); replace_call_with_value (gsi, dest);
return true; return true;
......
2018-03-12 Martin Sebor <msebor@redhat.com>
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 <hongjiu.lu@intel.com> 2018-03-12 H.J. Lu <hongjiu.lu@intel.com>
* g++.dg/pr84821.C: New test. * g++.dg/pr84821.C: New test.
......
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
static void wrap_memcpy (void *d, const void *s, size_t n) 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; const void *s = d + 1;
wrap_memcpy (d, s, n); wrap_memcpy (d, s, 2);
} }
......
...@@ -52,7 +52,6 @@ void test_memcpy_cst (void *d, const void *s) ...@@ -52,7 +52,6 @@ void test_memcpy_cst (void *d, const void *s)
} while (0) } while (0)
T (a, a, 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 /* This isn't detected because memcpy calls with small power-of-2 sizes
are intentionally folded into safe copies equivalent to memmove. are intentionally folded into safe copies equivalent to memmove.
...@@ -64,19 +63,6 @@ void test_memcpy_cst (void *d, const void *s) ...@@ -64,19 +63,6 @@ void test_memcpy_cst (void *d, const void *s)
T (a, a + 3, 5); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */ 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]; char a[3][7];
sink (a); sink (a);
...@@ -116,11 +102,6 @@ void test_memcpy_cst (void *d, const void *s) ...@@ -116,11 +102,6 @@ void test_memcpy_cst (void *d, const void *s)
memcpy (d, s, sizeof x.a); memcpy (d, s, sizeof x.a);
sink (&x); sink (&x);
d = x.a;
s = x.a;
memcpy (d, s, sizeof x.a); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
sink (&x);
d = x.a + 4; d = x.a + 4;
s = x.b; s = x.b;
memcpy (d, s, sizeof x.a); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */ memcpy (d, s, sizeof x.a); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
...@@ -447,22 +428,10 @@ void test_memcpy_var (char *d, const char *s) ...@@ -447,22 +428,10 @@ void test_memcpy_var (char *d, const char *s)
{ {
size_t n = unsigned_value (); size_t n = unsigned_value ();
/* Since no copying takes place no warning should be issued. */
memcpy (d, d, 0); memcpy (d, d, 0);
sink (d); 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. */ /* The following overlaps if n is greater than 1. */
s = d + 1; s = d + 1;
memcpy (d, s, n); memcpy (d, s, n);
...@@ -499,10 +468,6 @@ void test_memcpy_var (char *d, const char *s) ...@@ -499,10 +468,6 @@ void test_memcpy_var (char *d, const char *s)
s = d + 5; s = d + 5;
n = 7; n = 7;
memcpy (d, s, n); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */ 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) ...@@ -941,7 +906,7 @@ void test_strncpy_range (char *d, size_t n)
/* The following overlaps except in the unlikely case that value () /* The following overlaps except in the unlikely case that value ()
is zero, so it's diagnosed. */ 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" } */
} }
......
/* 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);
}
/* 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);
}
...@@ -1801,6 +1801,8 @@ bool ...@@ -1801,6 +1801,8 @@ bool
maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt) maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt)
{ {
gimple *stmt = gsi_stmt (gsi); gimple *stmt = gsi_stmt (gsi);
if (gimple_no_warning_p (stmt))
return false;
wide_int cntrange[2]; wide_int cntrange[2];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment