[C++ PATCH] -Wsizeof-pointer-memaccess warning
Jakub Jelinek
jakub@redhat.com
Thu Aug 16 19:20:00 GMT 2012
Hi!
And here is the C++ FE part of the patch. There were two issues
I didn't know about when starting the patch, one is that
for say the <string.h> _FORTIFY_SOURCE gnu_inline extern inline
memset etc. wrappers the C++ FE dropped BUILT_IN_NORMAL class,
so it stopped acting as builtin and therefore e.g. even the warning couldn't
find out it is a builtin (fixed by the decl.c change), and also for
templates, while sizeof (expr) always results with processing_template_decl
into SIZEOF_EXPR with original sizeof argument, for non-dependent types
it was folded immediately into a constant. I hope that for calls in
templates it is not a big deal if even that stays in the SIZEOF_EXPR form
(folded immediately, but changed back to SIZEOF_EXPR form before calling
finish_call_expr).
Bootstrapped/regtested on x68_64-linux and i686-linux on top of the
C -Wsizeof-pointer-memaccess patch (and as mentioned in that patch,
this actually found a bug in GCC itself already). Ok for trunk?
2012-08-16 Jakub Jelinek <jakub@redhat.com>
cp/
* cp-tree.h (struct cp_tree_loc_pair): New type.
(finish_call_expr): Adjust prototype.
* parser.c (cp_parser_parenthesized_expression_list): Add
sizeof_arg argument, fill it in.
(cp_parser_userdef_char_literal, cp_parser_userdef_numeric_literal,
cp_parser_userdef_string_literal, cp_parser_perform_range_for_lookup,
cp_parser_range_for_member_function): Adjust finish_call_expr
callers.
(cp_parser_postfix_expression): Adjust finish_call_expr and
cp_parser_parenthesized_expression_list callers. Pass sizeof_arg
through.
(cp_last_sizeof_arg): New variable.
(cp_parser_unary_expression): Fill it in for RID_SIZEOF.
(cp_parser_new_placement, cp_parser_new_initializer,
cp_parser_mem_initializer, cp_parser_initializer,
cp_parser_attribute_list, cp_parser_functional_cast): Adjust
cp_parser_parenthesized_expression_list callers.
* pt.c (tsubst_copy_and_build): Adjust finish_call_expr callers,
pass through sizeof_arg.
* semantics.c (finish_call_expr): Add sizeof_arg argument.
Call sizeof_pointer_memaccess_warning if needed.
(finish_omp_barrier, finish_omp_flush, finish_omp_taskwait,
finish_omp_taskyield): Adjust finish_call_expr callers.
* decl.c (duplicate_decls): When redeclaring a builtin function,
keep the merged decl builtin also if newdecl is a gnu_inline
inline definition.
testsuite/
* g++.dg/torture/Wsizeof-pointer-memaccess1.C: New test.
* g++.dg/torture/Wsizeof-pointer-memaccess2.C: New test.
* g++.dg/ext/builtin30.C: New test.
* gcc.dg/builtins-85.c: New test.
--- gcc/cp/parser.c.jj 2012-08-15 10:55:24.000000000 +0200
+++ gcc/cp/parser.c 2012-08-16 16:47:56.439684336 +0200
@@ -1803,7 +1803,7 @@ static tree cp_parser_postfix_open_squar
static tree cp_parser_postfix_dot_deref_expression
(cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
static VEC(tree,gc) *cp_parser_parenthesized_expression_list
- (cp_parser *, int, bool, bool, bool *);
+ (cp_parser *, int, bool, bool, bool *, struct cp_tree_loc_pair *);
/* Values for the second parameter of cp_parser_parenthesized_expression_list. */
enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
static void cp_parser_pseudo_destructor_name
@@ -3583,7 +3583,8 @@ cp_parser_userdef_char_literal (cp_parse
release_tree_vector (args);
return error_mark_node;
}
- result = finish_call_expr (decl, &args, false, true, tf_warning_or_error);
+ result = finish_call_expr (decl, &args, false, true, NULL,
+ tf_warning_or_error);
release_tree_vector (args);
if (result != error_mark_node)
return result;
@@ -3641,7 +3642,7 @@ cp_parser_userdef_numeric_literal (cp_pa
decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
- result = finish_call_expr (decl, &args, false, true, tf_none);
+ result = finish_call_expr (decl, &args, false, true, NULL, tf_none);
if (result != error_mark_node)
{
release_tree_vector (args);
@@ -3658,7 +3659,7 @@ cp_parser_userdef_numeric_literal (cp_pa
decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
- result = finish_call_expr (decl, &args, false, true, tf_none);
+ result = finish_call_expr (decl, &args, false, true, NULL, tf_none);
if (result != error_mark_node)
{
release_tree_vector (args);
@@ -3676,7 +3677,7 @@ cp_parser_userdef_numeric_literal (cp_pa
{
tree tmpl_args = make_char_string_pack (num_string);
decl = lookup_template_function (decl, tmpl_args);
- result = finish_call_expr (decl, &args, false, true, tf_none);
+ result = finish_call_expr (decl, &args, false, true, NULL, tf_none);
if (result != error_mark_node)
{
release_tree_vector (args);
@@ -3716,7 +3717,7 @@ cp_parser_userdef_string_literal (cp_tok
release_tree_vector (args);
return error_mark_node;
}
- result = finish_call_expr (decl, &args, false, true, tf_none);
+ result = finish_call_expr (decl, &args, false, true, NULL, tf_none);
release_tree_vector (args);
if (result != error_mark_node)
return result;
@@ -5468,7 +5469,7 @@ cp_parser_postfix_expression (cp_parser
cp_lexer_consume_token (parser->lexer);
vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/false, /*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+ /*non_constant_p=*/NULL, /*sizeof_arg=*/NULL);
if (vec == NULL)
return error_mark_node;
@@ -5624,6 +5625,7 @@ cp_parser_postfix_expression (cp_parser
bool saved_integral_constant_expression_p = false;
bool saved_non_integral_constant_expression_p = false;
VEC(tree,gc) *args;
+ struct cp_tree_loc_pair sizeof_arg;
is_member_access = false;
@@ -5642,7 +5644,7 @@ cp_parser_postfix_expression (cp_parser
args = (cp_parser_parenthesized_expression_list
(parser, non_attr,
/*cast_p=*/false, /*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL));
+ /*non_constant_p=*/NULL, &sizeof_arg));
if (is_builtin_constant_p)
{
parser->integral_constant_expression_p
@@ -5746,6 +5748,7 @@ cp_parser_postfix_expression (cp_parser
= finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
+ /*sizeof_arg=*/NULL,
tf_warning_or_error);
}
else if (TREE_CODE (postfix_expression) == OFFSET_REF
@@ -5753,21 +5756,43 @@ cp_parser_postfix_expression (cp_parser
|| TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
postfix_expression = (build_offset_ref_call_from_tree
(postfix_expression, &args));
- else if (idk == CP_ID_KIND_QUALIFIED)
- /* A call to a static class member, or a namespace-scope
- function. */
- postfix_expression
- = finish_call_expr (postfix_expression, &args,
- /*disallow_virtual=*/true,
- koenig_p,
- tf_warning_or_error);
else
- /* All other function calls. */
- postfix_expression
- = finish_call_expr (postfix_expression, &args,
- /*disallow_virtual=*/false,
- koenig_p,
- tf_warning_or_error);
+ {
+ /* In templates, for expressions SIZEOF_EXPR is always
+ created, but for types it is sometimes already folded.
+ Force use of SIZEOF_EXPR in that case anyway, so that
+ -Wsizeof-pointer-memaccess warning can work during
+ instantiation. */
+ if (processing_template_decl
+ && sizeof_arg.expr != NULL_TREE
+ && TYPE_P (sizeof_arg.expr)
+ && !VEC_empty (tree, args)
+ && TREE_CODE (VEC_last (tree, args)) == INTEGER_CST)
+ {
+ tree se = build_min (SIZEOF_EXPR, size_type_node,
+ sizeof_arg.expr);
+ TREE_SIDE_EFFECTS (se) = 0;
+ TREE_READONLY (se) = 1;
+ SET_EXPR_LOCATION (se, sizeof_arg.first_loc);
+ VEC_replace (tree, args, VEC_length (tree, args) - 1, se);
+ }
+
+ if (idk == CP_ID_KIND_QUALIFIED)
+ /* A call to a static class member, or a namespace-scope
+ function. */
+ postfix_expression
+ = finish_call_expr (postfix_expression, &args,
+ /*disallow_virtual=*/true,
+ koenig_p, &sizeof_arg,
+ tf_warning_or_error);
+ else
+ /* All other function calls. */
+ postfix_expression
+ = finish_call_expr (postfix_expression, &args,
+ /*disallow_virtual=*/false,
+ koenig_p, &sizeof_arg,
+ tf_warning_or_error);
+ }
/* The POSTFIX_EXPRESSION is certainly no longer an id. */
idk = CP_ID_KIND_NONE;
@@ -6084,6 +6109,10 @@ cp_parser_postfix_dot_deref_expression (
return postfix_expression;
}
+/* Argument of last sizeof expression, used for -Wsizeof-pointer-memaccess
+ warning. */
+static struct cp_tree_loc_pair cp_last_sizeof_arg;
+
/* Parse a parenthesized expression-list.
expression-list:
@@ -6115,17 +6144,26 @@ cp_parser_parenthesized_expression_list
int is_attribute_list,
bool cast_p,
bool allow_expansion_p,
- bool *non_constant_p)
+ bool *non_constant_p,
+ struct cp_tree_loc_pair *sizeof_arg)
{
VEC(tree,gc) *expression_list;
bool fold_expr_p = is_attribute_list != non_attr;
tree identifier = NULL_TREE;
bool saved_greater_than_is_operator_p;
+ location_t sizeof_arg_loc = UNKNOWN_LOCATION;
/* Assume all the expressions will be constant. */
if (non_constant_p)
*non_constant_p = false;
+ if (sizeof_arg != NULL)
+ {
+ sizeof_arg->expr = NULL_TREE;
+ sizeof_arg->first_loc = UNKNOWN_LOCATION;
+ sizeof_arg->last_loc = UNKNOWN_LOCATION;
+ }
+
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return NULL;
@@ -6143,6 +6181,8 @@ cp_parser_parenthesized_expression_list
{
tree expr;
+ sizeof_arg_loc = UNKNOWN_LOCATION;
+
/* At the beginning of attribute lists, check to see if the
next token is an identifier. */
if (is_attribute_list == id_attr
@@ -6177,7 +6217,14 @@ cp_parser_parenthesized_expression_list
*non_constant_p = true;
}
else
- expr = cp_parser_assignment_expression (parser, cast_p, NULL);
+ {
+ if (sizeof_arg != NULL
+ && cp_lexer_next_token_is_keyword (parser->lexer,
+ RID_SIZEOF))
+ sizeof_arg_loc
+ = cp_lexer_peek_nth_token (parser->lexer, 2)->location;
+ expr = cp_parser_assignment_expression (parser, cast_p, NULL);
+ }
if (fold_expr_p)
expr = fold_non_dependent_expr (expr);
@@ -6217,6 +6264,14 @@ cp_parser_parenthesized_expression_list
cp_lexer_consume_token (parser->lexer);
}
+ if (sizeof_arg != NULL
+ && sizeof_arg_loc != UNKNOWN_LOCATION
+ && cp_last_sizeof_arg.expr != NULL_TREE
+ && sizeof_arg_loc == cp_last_sizeof_arg.first_loc
+ && cp_lexer_peek_token (parser->lexer)->location
+ == cp_last_sizeof_arg.last_loc)
+ *sizeof_arg = cp_last_sizeof_arg;
+
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
{
int ending;
@@ -6385,17 +6440,26 @@ cp_parser_unary_expression (cp_parser *p
case RID_ALIGNOF:
case RID_SIZEOF:
{
- tree operand;
+ tree operand, result;
enum tree_code op;
+ location_t first_loc;
op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR;
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
+ first_loc = cp_lexer_peek_token (parser->lexer)->location;
/* Parse the operand. */
operand = cp_parser_sizeof_operand (parser, keyword);
+ if (keyword == RID_SIZEOF)
+ {
+ cp_last_sizeof_arg.expr = operand;
+ cp_last_sizeof_arg.first_loc = first_loc;
+ cp_last_sizeof_arg.last_loc
+ = cp_lexer_peek_token (parser->lexer)->location;
+ }
if (TYPE_P (operand))
- return cxx_sizeof_or_alignof_type (operand, op, true);
+ result = cxx_sizeof_or_alignof_type (operand, op, true);
else
{
/* ISO C++ defines alignof only with types, not with
@@ -6406,8 +6470,14 @@ cp_parser_unary_expression (cp_parser *p
"ISO C++ does not allow %<alignof%> "
"with a non-type");
- return cxx_sizeof_or_alignof_expr (operand, op, true);
+ result = cxx_sizeof_or_alignof_expr (operand, op, true);
}
+
+ if (processing_template_decl
+ && TREE_CODE (result) == SIZEOF_EXPR)
+ SET_EXPR_LOCATION (result, first_loc);
+
+ return result;
}
case RID_NEW:
@@ -6761,7 +6831,7 @@ cp_parser_new_placement (cp_parser* pars
expression_list = (cp_parser_parenthesized_expression_list
(parser, non_attr, /*cast_p=*/false,
/*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL));
+ /*non_constant_p=*/NULL, /*sizeof_arg=*/NULL));
return expression_list;
}
@@ -6963,7 +7033,7 @@ cp_parser_new_initializer (cp_parser* pa
expression_list = (cp_parser_parenthesized_expression_list
(parser, non_attr, /*cast_p=*/false,
/*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL));
+ /*non_constant_p=*/NULL, /*sizeof_arg=*/NULL));
return expression_list;
}
@@ -9608,12 +9678,12 @@ cp_parser_perform_range_for_lookup (tree
member_begin = perform_koenig_lookup (id_begin, vec,
/*include_std=*/true,
tf_warning_or_error);
- *begin = finish_call_expr (member_begin, &vec, false, true,
+ *begin = finish_call_expr (member_begin, &vec, false, true, NULL,
tf_warning_or_error);
member_end = perform_koenig_lookup (id_end, vec,
/*include_std=*/true,
tf_warning_or_error);
- *end = finish_call_expr (member_end, &vec, false, true,
+ *end = finish_call_expr (member_end, &vec, false, true, NULL,
tf_warning_or_error);
release_tree_vector (vec);
@@ -9657,7 +9727,7 @@ cp_parser_range_for_member_function (tre
vec = make_tree_vector ();
res = finish_call_expr (member, &vec,
/*disallow_virtual=*/false,
- /*koenig_p=*/false,
+ /*koenig_p=*/false, /*sizeof_arg=*/NULL,
tf_warning_or_error);
release_tree_vector (vec);
return res;
@@ -11513,7 +11583,8 @@ cp_parser_mem_initializer (cp_parser* pa
vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/false,
/*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+ /*non_constant_p=*/NULL,
+ /*sizeof_arg=*/NULL);
if (vec == NULL)
return error_mark_node;
expression_list = build_tree_list_vec (vec);
@@ -17548,7 +17619,8 @@ cp_parser_initializer (cp_parser* parser
vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/false,
/*allow_expansion_p=*/true,
- non_constant_p);
+ non_constant_p,
+ /*sizeof_arg=*/NULL);
if (vec == NULL)
return error_mark_node;
init = build_tree_list_vec (vec);
@@ -20223,7 +20295,7 @@ cp_parser_attribute_list (cp_parser* par
vec = cp_parser_parenthesized_expression_list
(parser, attr_flag, /*cast_p=*/false,
/*allow_expansion_p=*/false,
- /*non_constant_p=*/NULL);
+ /*non_constant_p=*/NULL, /*sizeof_arg=*/NULL);
if (vec == NULL)
arguments = error_mark_node;
else
@@ -21484,7 +21556,8 @@ cp_parser_functional_cast (cp_parser* pa
vec = cp_parser_parenthesized_expression_list (parser, non_attr,
/*cast_p=*/true,
/*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+ /*non_constant_p=*/NULL,
+ /*sizeof_arg=*/NULL);
if (vec == NULL)
expression_list = error_mark_node;
else
--- gcc/cp/pt.c.jj 2012-08-10 12:57:26.000000000 +0200
+++ gcc/cp/pt.c 2012-08-16 16:02:12.230154801 +0200
@@ -13500,7 +13500,11 @@ tsubst_copy_and_build (tree t,
bool qualified_p;
bool koenig_p;
tree ret;
+ struct cp_tree_loc_pair sizeof_arg;
+ sizeof_arg.expr = NULL_TREE;
+ sizeof_arg.first_loc = UNKNOWN_LOCATION;
+ sizeof_arg.last_loc = UNKNOWN_LOCATION;
function = CALL_EXPR_FN (t);
/* When we parsed the expression, we determined whether or
not Koenig lookup should be performed. */
@@ -13555,8 +13559,18 @@ tsubst_copy_and_build (tree t,
tree arg = CALL_EXPR_ARG (t, i);
if (!PACK_EXPANSION_P (arg))
- VEC_safe_push (tree, gc, call_args,
- RECUR (CALL_EXPR_ARG (t, i)));
+ {
+ VEC_safe_push (tree, gc, call_args,
+ RECUR (CALL_EXPR_ARG (t, i)));
+ if (i == nargs - 1
+ && TREE_CODE (CALL_EXPR_ARG (t, i)) == SIZEOF_EXPR)
+ {
+ sizeof_arg.expr
+ = RECUR (TREE_OPERAND (CALL_EXPR_ARG (t, i), 0));
+ sizeof_arg.first_loc
+ = EXPR_LOCATION (CALL_EXPR_ARG (t, i));
+ }
+ }
else
{
/* Expand the pack expansion and push each entry onto
@@ -13678,9 +13692,9 @@ tsubst_copy_and_build (tree t,
ret = build_nt_call_vec (function, call_args);
else if (!BASELINK_P (fn))
ret = finish_call_expr (function, &call_args,
- /*disallow_virtual=*/false,
- /*koenig_p=*/false,
- complain);
+ /*disallow_virtual=*/false,
+ /*koenig_p=*/false, /*sizeof_arg=*/NULL,
+ complain);
else
ret = (build_new_method_call
(instance, fn,
@@ -13692,7 +13706,7 @@ tsubst_copy_and_build (tree t,
else
ret = finish_call_expr (function, &call_args,
/*disallow_virtual=*/qualified_p,
- koenig_p,
+ koenig_p, &sizeof_arg,
complain);
release_tree_vector (call_args);
--- gcc/cp/semantics.c.jj 2012-08-15 10:55:24.000000000 +0200
+++ gcc/cp/semantics.c 2012-08-16 15:27:45.791077750 +0200
@@ -2030,7 +2030,8 @@ perform_koenig_lookup (tree fn, VEC(tree
tree
finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual,
- bool koenig_p, tsubst_flags_t complain)
+ bool koenig_p, struct cp_tree_loc_pair *sizeof_arg,
+ tsubst_flags_t complain)
{
tree result;
tree orig_fn;
@@ -2160,8 +2161,18 @@ finish_call_expr (tree fn, VEC(tree,gc)
result = resolve_overloaded_builtin (input_location, fn, *args);
if (!result)
- /* A call to a namespace-scope function. */
- result = build_new_function_call (fn, args, koenig_p, complain);
+ {
+ if (warn_sizeof_pointer_memaccess
+ && sizeof_arg != NULL
+ && !processing_template_decl
+ && sizeof_arg->expr != NULL_TREE)
+ sizeof_pointer_memaccess_warning
+ (sizeof_arg->first_loc, fn, *args, sizeof_arg->expr,
+ same_type_ignoring_top_level_qualifiers_p);
+
+ /* A call to a namespace-scope function. */
+ result = build_new_function_call (fn, args, koenig_p, complain);
+ }
}
else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
{
@@ -4973,7 +4984,8 @@ finish_omp_barrier (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
VEC(tree,gc) *vec = make_tree_vector ();
- tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ tree stmt = finish_call_expr (fn, &vec, false, false, NULL,
+ tf_warning_or_error);
release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -4983,7 +4995,8 @@ finish_omp_flush (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
VEC(tree,gc) *vec = make_tree_vector ();
- tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ tree stmt = finish_call_expr (fn, &vec, false, false, NULL,
+ tf_warning_or_error);
release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -4993,7 +5006,8 @@ finish_omp_taskwait (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
VEC(tree,gc) *vec = make_tree_vector ();
- tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ tree stmt = finish_call_expr (fn, &vec, false, false, NULL,
+ tf_warning_or_error);
release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -5003,7 +5017,8 @@ finish_omp_taskyield (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
VEC(tree,gc) *vec = make_tree_vector ();
- tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ tree stmt = finish_call_expr (fn, &vec, false, false, NULL,
+ tf_warning_or_error);
release_tree_vector (vec);
finish_expr_stmt (stmt);
}
--- gcc/cp/decl.c.jj 2012-08-15 10:55:24.044296935 +0200
+++ gcc/cp/decl.c 2012-08-16 15:40:25.729437019 +0200
@@ -2154,39 +2154,40 @@ duplicate_decls (tree newdecl, tree oldd
DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
}
+ /* If redeclaring a builtin function, it stays built in
+ if newdecl is a gnu_inline definition, or if newdecl is just
+ a declaration. */
+ if (DECL_BUILT_IN (olddecl)
+ && (new_defines_function ? GNU_INLINE_P (newdecl) : types_match))
+ {
+ DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
+ DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+ /* If we're keeping the built-in definition, keep the rtl,
+ regardless of declaration matches. */
+ COPY_DECL_RTL (olddecl, newdecl);
+ if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
+ {
+ enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+ switch (fncode)
+ {
+ /* If a compatible prototype of these builtin functions
+ is seen, assume the runtime implements it with the
+ expected semantics. */
+ case BUILT_IN_STPCPY:
+ if (builtin_decl_explicit_p (fncode))
+ set_builtin_decl_implicit_p (fncode, true);
+ break;
+ default:
+ break;
+ }
+ }
+ }
if (new_defines_function)
/* If defining a function declared with other language
linkage, use the previously declared language linkage. */
SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
else if (types_match)
{
- /* If redeclaring a builtin function, and not a definition,
- it stays built in. */
- if (DECL_BUILT_IN (olddecl))
- {
- DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
- DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
- /* If we're keeping the built-in definition, keep the rtl,
- regardless of declaration matches. */
- COPY_DECL_RTL (olddecl, newdecl);
- if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
- {
- enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
- switch (fncode)
- {
- /* If a compatible prototype of these builtin functions
- is seen, assume the runtime implements it with the
- expected semantics. */
- case BUILT_IN_STPCPY:
- if (builtin_decl_explicit_p (fncode))
- set_builtin_decl_implicit_p (fncode, true);
- break;
- default:
- break;
- }
- }
- }
-
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
/* Don't clear out the arguments if we're just redeclaring a
function. */
--- gcc/cp/cp-tree.h.jj 2012-08-10 12:57:26.000000000 +0200
+++ gcc/cp/cp-tree.h 2012-08-16 12:28:29.062398331 +0200
@@ -5496,6 +5496,12 @@ typedef struct GTY(()) deferred_access_c
DEF_VEC_O(deferred_access_check);
DEF_VEC_ALLOC_O(deferred_access_check,gc);
+/* Used for -Wsizeof-pointer-memaccess diagnostics. */
+struct cp_tree_loc_pair {
+ tree expr;
+ location_t first_loc, last_loc;
+};
+
/* in semantics.c */
extern void push_deferring_access_checks (deferring_kind);
extern void resume_deferring_access_checks (void);
@@ -5591,7 +5597,8 @@ bool empty_expr_stmt_p (tree);
extern tree perform_koenig_lookup (tree, VEC(tree,gc) *, bool,
tsubst_flags_t);
extern tree finish_call_expr (tree, VEC(tree,gc) **, bool,
- bool, tsubst_flags_t);
+ bool, struct cp_tree_loc_pair *,
+ tsubst_flags_t);
extern tree finish_increment_expr (tree, enum tree_code);
extern tree finish_this_expr (void);
extern tree finish_pseudo_destructor_expr (tree, tree, tree);
--- gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C.jj 2012-08-16 15:41:25.594150006 +0200
+++ gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C 2012-08-16 15:51:04.199374022 +0200
@@ -0,0 +1,716 @@
+// Test -Wsizeof-pointer-memaccess warnings.
+// { dg-do compile }
+// { dg-options "-Wall" }
+// Test just twice, once with -O0 non-fortified, once with -O2 fortified.
+// { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } }
+// { dg-skip-if "" { *-*-* } { "-flto" } { "" } }
+
+extern "C" {
+
+typedef __SIZE_TYPE__ size_t;
+extern void *memset (void *, int, size_t);
+extern void *memcpy (void *__restrict, const void *__restrict, size_t);
+extern void *memmove (void *__restrict, const void *__restrict, size_t);
+extern int memcmp (const void *, const void *, size_t);
+extern char *strncpy (char *__restrict, const char *__restrict, size_t);
+extern char *strncat (char *__restrict, const char *__restrict, size_t);
+extern char *strndup (const char *, size_t);
+extern int strncmp (const char *, const char *, size_t);
+extern int strncasecmp (const char *, const char *, size_t);
+
+#ifdef __OPTIMIZE__
+# define bos(ptr) __builtin_object_size (ptr, 1)
+# define bos0(ptr) __builtin_object_size (ptr, 0)
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memset (void *dest, int c, size_t len)
+{
+ return __builtin___memset_chk (dest, c, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memcpy (void *__restrict dest, const void *__restrict src, size_t len)
+{
+ return __builtin___memcpy_chk (dest, src, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memmove (void *dest, const void *src, size_t len)
+{
+ return __builtin___memmove_chk (dest, src, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline char *
+strncpy (char *__restrict dest, const char *__restrict src, size_t len)
+{
+ return __builtin___strncpy_chk (dest, src, len, bos (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline char *
+strncat (char *dest, const char *src, size_t len)
+{
+ return __builtin___strncat_chk (dest, src, len, bos (dest));
+}
+#endif
+
+}
+
+struct A { short a, b; int c, d; long e, f; };
+typedef struct A TA;
+typedef struct A *PA;
+typedef TA *PTA;
+struct B {};
+typedef struct B TB;
+typedef struct B *PB;
+typedef TB *PTB;
+typedef int X[3][3][3];
+
+template <int N>
+int
+f1 (void *x, int z)
+{
+ struct A a, *pa1 = &a;
+ TA *pa2 = &a;
+ PA pa3 = &a;
+ PTA pa4 = &a;
+ memset (&a, 0, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memset (pa1, 0, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pa2, 0, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pa3, 0, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pa4, 0, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pa1, 0, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pa2, 0, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pa3, 0, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pa4, 0, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memcpy (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memcpy (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pa1, x, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pa4, x, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memcpy (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memcpy (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pa1, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pa4, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ memmove (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memmove (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pa1, x, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pa4, x, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memmove (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memmove (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pa1, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pa4, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ z += memcmp (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ z += memcmp (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pa1, x, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ z += memcmp (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ z += memcmp (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pa1, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ // These are correct, no warning.
+ memset (&a, 0, sizeof a);
+ memset (&a, 0, sizeof (a));
+ memset (&a, 0, sizeof (struct A));
+ memset (&a, 0, sizeof (const struct A));
+ memset (&a, 0, sizeof (volatile struct A));
+ memset (&a, 0, sizeof (volatile const struct A));
+ memset (&a, 0, sizeof (TA));
+ memset (&a, 0, sizeof (__typeof (*&a)));
+ memset (pa1, 0, sizeof (*pa1));
+ memset (pa2, 0, sizeof (*pa3));
+ memset (pa3, 0, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ memset ((void *) &a, 0, sizeof (&a));
+ memset ((char *) &a, 0, sizeof (&a));
+ memset (&a, 0, sizeof (&a) + 0);
+ memset (&a, 0, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ memcpy (&a, x, sizeof a);
+ memcpy (&a, x, sizeof (a));
+ memcpy (&a, x, sizeof (struct A));
+ memcpy (&a, x, sizeof (const struct A));
+ memcpy (&a, x, sizeof (volatile struct A));
+ memcpy (&a, x, sizeof (volatile const struct A));
+ memcpy (&a, x, sizeof (TA));
+ memcpy (&a, x, sizeof (__typeof (*&a)));
+ memcpy (pa1, x, sizeof (*pa1));
+ memcpy (pa2, x, sizeof (*pa3));
+ memcpy (pa3, x, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy ((void *) &a, x, sizeof (&a));
+ memcpy ((char *) &a, x, sizeof (&a));
+ memcpy (&a, x, sizeof (&a) + 0);
+ memcpy (&a, x, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ memcpy (x, &a, sizeof a);
+ memcpy (x, &a, sizeof (a));
+ memcpy (x, &a, sizeof (struct A));
+ memcpy (x, &a, sizeof (const struct A));
+ memcpy (x, &a, sizeof (volatile struct A));
+ memcpy (x, &a, sizeof (volatile const struct A));
+ memcpy (x, &a, sizeof (TA));
+ memcpy (x, &a, sizeof (__typeof (*&a)));
+ memcpy (x, pa1, sizeof (*pa1));
+ memcpy (x, pa2, sizeof (*pa3));
+ memcpy (x, pa3, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy (x, (void *) &a, sizeof (&a));
+ memcpy (x, (char *) &a, sizeof (&a));
+ memcpy (x, &a, sizeof (&a) + 0);
+ memcpy (x, &a, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ memmove (&a, x, sizeof a);
+ memmove (&a, x, sizeof (a));
+ memmove (&a, x, sizeof (struct A));
+ memmove (&a, x, sizeof (const struct A));
+ memmove (&a, x, sizeof (volatile struct A));
+ memmove (&a, x, sizeof (volatile const struct A));
+ memmove (&a, x, sizeof (TA));
+ memmove (&a, x, sizeof (__typeof (*&a)));
+ memmove (pa1, x, sizeof (*pa1));
+ memmove (pa2, x, sizeof (*pa3));
+ memmove (pa3, x, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ memmove ((void *) &a, x, sizeof (&a));
+ memmove ((char *) &a, x, sizeof (&a));
+ memmove (&a, x, sizeof (&a) + 0);
+ memmove (&a, x, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ memmove (x, &a, sizeof a);
+ memmove (x, &a, sizeof (a));
+ memmove (x, &a, sizeof (struct A));
+ memmove (x, &a, sizeof (const struct A));
+ memmove (x, &a, sizeof (volatile struct A));
+ memmove (x, &a, sizeof (volatile const struct A));
+ memmove (x, &a, sizeof (TA));
+ memmove (x, &a, sizeof (__typeof (*&a)));
+ memmove (x, pa1, sizeof (*pa1));
+ memmove (x, pa2, sizeof (*pa3));
+ memmove (x, pa3, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ memmove (x, (void *) &a, sizeof (&a));
+ memmove (x, (char *) &a, sizeof (&a));
+ memmove (x, &a, sizeof (&a) + 0);
+ memmove (x, &a, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ z += memcmp (&a, x, sizeof a);
+ z += memcmp (&a, x, sizeof (a));
+ z += memcmp (&a, x, sizeof (struct A));
+ z += memcmp (&a, x, sizeof (const struct A));
+ z += memcmp (&a, x, sizeof (volatile struct A));
+ z += memcmp (&a, x, sizeof (volatile const struct A));
+ z += memcmp (&a, x, sizeof (TA));
+ z += memcmp (&a, x, sizeof (__typeof (*&a)));
+ z += memcmp (pa1, x, sizeof (*pa1));
+ z += memcmp (pa2, x, sizeof (*pa3));
+ z += memcmp (pa3, x, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp ((void *) &a, x, sizeof (&a));
+ z += memcmp ((char *) &a, x, sizeof (&a));
+ z += memcmp (&a, x, sizeof (&a) + 0);
+ z += memcmp (&a, x, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ z += memcmp (x, &a, sizeof a);
+ z += memcmp (x, &a, sizeof (a));
+ z += memcmp (x, &a, sizeof (struct A));
+ z += memcmp (x, &a, sizeof (const struct A));
+ z += memcmp (x, &a, sizeof (volatile struct A));
+ z += memcmp (x, &a, sizeof (volatile const struct A));
+ z += memcmp (x, &a, sizeof (TA));
+ z += memcmp (x, &a, sizeof (__typeof (*&a)));
+ z += memcmp (x, pa1, sizeof (*pa1));
+ z += memcmp (x, pa2, sizeof (*pa3));
+ z += memcmp (x, pa3, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp (x, (void *) &a, sizeof (&a));
+ z += memcmp (x, (char *) &a, sizeof (&a));
+ z += memcmp (x, &a, sizeof (&a) + 0);
+ z += memcmp (x, &a, 0 + sizeof (&a));
+
+ return z;
+}
+
+template <int N>
+int
+f2 (void *x, int z)
+{
+ struct B b, *pb1 = &b;
+ TB *pb2 = &b;
+ PB pb3 = &b;
+ PTB pb4 = &b;
+ memset (&b, 0, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memset (pb1, 0, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pb2, 0, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pb3, 0, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pb4, 0, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pb1, 0, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pb2, 0, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pb3, 0, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pb4, 0, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memcpy (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memcpy (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pb1, x, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pb4, x, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memcpy (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memcpy (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pb1, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pb4, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ memmove (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memmove (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pb1, x, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pb4, x, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memmove (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memmove (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pb1, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pb4, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ z += memcmp (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ z += memcmp (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pb1, x, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ z += memcmp (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ z += memcmp (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pb1, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ // These are correct, no warning.
+ memset (&b, 0, sizeof b);
+ memset (&b, 0, sizeof (b));
+ memset (&b, 0, sizeof (struct B));
+ memset (&b, 0, sizeof (const struct B));
+ memset (&b, 0, sizeof (volatile struct B));
+ memset (&b, 0, sizeof (volatile const struct B));
+ memset (&b, 0, sizeof (TB));
+ memset (&b, 0, sizeof (__typeof (*&b)));
+ memset (pb1, 0, sizeof (*pb1));
+ memset (pb2, 0, sizeof (*pb3));
+ memset (pb3, 0, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ memset ((void *) &b, 0, sizeof (&b));
+ memset ((char *) &b, 0, sizeof (&b));
+ memset (&b, 0, sizeof (&b) + 0);
+ memset (&b, 0, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ memcpy (&b, x, sizeof b);
+ memcpy (&b, x, sizeof (b));
+ memcpy (&b, x, sizeof (struct B));
+ memcpy (&b, x, sizeof (const struct B));
+ memcpy (&b, x, sizeof (volatile struct B));
+ memcpy (&b, x, sizeof (volatile const struct B));
+ memcpy (&b, x, sizeof (TB));
+ memcpy (&b, x, sizeof (__typeof (*&b)));
+ memcpy (pb1, x, sizeof (*pb1));
+ memcpy (pb2, x, sizeof (*pb3));
+ memcpy (pb3, x, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy ((void *) &b, x, sizeof (&b));
+ memcpy ((char *) &b, x, sizeof (&b));
+ memcpy (&b, x, sizeof (&b) + 0);
+ memcpy (&b, x, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ memcpy (x, &b, sizeof b);
+ memcpy (x, &b, sizeof (b));
+ memcpy (x, &b, sizeof (struct B));
+ memcpy (x, &b, sizeof (const struct B));
+ memcpy (x, &b, sizeof (volatile struct B));
+ memcpy (x, &b, sizeof (volatile const struct B));
+ memcpy (x, &b, sizeof (TB));
+ memcpy (x, &b, sizeof (__typeof (*&b)));
+ memcpy (x, pb1, sizeof (*pb1));
+ memcpy (x, pb2, sizeof (*pb3));
+ memcpy (x, pb3, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy (x, (void *) &b, sizeof (&b));
+ memcpy (x, (char *) &b, sizeof (&b));
+ memcpy (x, &b, sizeof (&b) + 0);
+ memcpy (x, &b, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ memmove (&b, x, sizeof b);
+ memmove (&b, x, sizeof (b));
+ memmove (&b, x, sizeof (struct B));
+ memmove (&b, x, sizeof (const struct B));
+ memmove (&b, x, sizeof (volatile struct B));
+ memmove (&b, x, sizeof (volatile const struct B));
+ memmove (&b, x, sizeof (TB));
+ memmove (&b, x, sizeof (__typeof (*&b)));
+ memmove (pb1, x, sizeof (*pb1));
+ memmove (pb2, x, sizeof (*pb3));
+ memmove (pb3, x, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ memmove ((void *) &b, x, sizeof (&b));
+ memmove ((char *) &b, x, sizeof (&b));
+ memmove (&b, x, sizeof (&b) + 0);
+ memmove (&b, x, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ memmove (x, &b, sizeof b);
+ memmove (x, &b, sizeof (b));
+ memmove (x, &b, sizeof (struct B));
+ memmove (x, &b, sizeof (const struct B));
+ memmove (x, &b, sizeof (volatile struct B));
+ memmove (x, &b, sizeof (volatile const struct B));
+ memmove (x, &b, sizeof (TB));
+ memmove (x, &b, sizeof (__typeof (*&b)));
+ memmove (x, pb1, sizeof (*pb1));
+ memmove (x, pb2, sizeof (*pb3));
+ memmove (x, pb3, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ memmove (x, (void *) &b, sizeof (&b));
+ memmove (x, (char *) &b, sizeof (&b));
+ memmove (x, &b, sizeof (&b) + 0);
+ memmove (x, &b, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ z += memcmp (&b, x, sizeof b);
+ z += memcmp (&b, x, sizeof (b));
+ z += memcmp (&b, x, sizeof (struct B));
+ z += memcmp (&b, x, sizeof (const struct B));
+ z += memcmp (&b, x, sizeof (volatile struct B));
+ z += memcmp (&b, x, sizeof (volatile const struct B));
+ z += memcmp (&b, x, sizeof (TB));
+ z += memcmp (&b, x, sizeof (__typeof (*&b)));
+ z += memcmp (pb1, x, sizeof (*pb1));
+ z += memcmp (pb2, x, sizeof (*pb3));
+ z += memcmp (pb3, x, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp ((void *) &b, x, sizeof (&b));
+ z += memcmp ((char *) &b, x, sizeof (&b));
+ z += memcmp (&b, x, sizeof (&b) + 0);
+ z += memcmp (&b, x, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ z += memcmp (x, &b, sizeof b);
+ z += memcmp (x, &b, sizeof (b));
+ z += memcmp (x, &b, sizeof (struct B));
+ z += memcmp (x, &b, sizeof (const struct B));
+ z += memcmp (x, &b, sizeof (volatile struct B));
+ z += memcmp (x, &b, sizeof (volatile const struct B));
+ z += memcmp (x, &b, sizeof (TB));
+ z += memcmp (x, &b, sizeof (__typeof (*&b)));
+ z += memcmp (x, pb1, sizeof (*pb1));
+ z += memcmp (x, pb2, sizeof (*pb3));
+ z += memcmp (x, pb3, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp (x, (void *) &b, sizeof (&b));
+ z += memcmp (x, (char *) &b, sizeof (&b));
+ z += memcmp (x, &b, sizeof (&b) + 0);
+ z += memcmp (x, &b, 0 + sizeof (&b));
+
+ return z;
+}
+
+template <int N>
+int
+f3 (void *x, char *y, int z, X w)
+{
+ unsigned char *y1 = (unsigned char *) __builtin_alloca (z + 16);
+ char buf1[7];
+ signed char buf2[z + 32];
+ long buf3[17];
+ int *buf4[9];
+ signed char *y2 = buf2;
+ char c;
+ char *y3;
+ memset (y, 0, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memset (y1, 0, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memset (y2, 0, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memset (&c, 0, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memset (w, 0, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+ memcpy (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memcpy (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memcpy (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memcpy (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memcpy (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+ memcpy (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memcpy (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memcpy (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memcpy (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memcpy (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+ memmove (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memmove (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memmove (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memmove (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memmove (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+ memmove (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memmove (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memmove (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memmove (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memmove (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+ z += memcmp (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ z += memcmp (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ z += memcmp (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ z += memcmp (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ z += memcmp (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+ z += memcmp (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ z += memcmp (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ z += memcmp (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ z += memcmp (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ z += memcmp (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+ // These are correct, no warning.
+ memset (y, 0, sizeof (*y));
+ memset (y1, 0, sizeof (*y2));
+ memset (buf1, 0, sizeof buf1);
+ memset (buf3, 0, sizeof (buf3));
+ memset (&buf3[0], 0, sizeof (buf3));
+ memset (&buf4[0], 0, sizeof (buf4));
+ memset (w, 0, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ memset ((void *) y, 0, sizeof (y));
+ memset ((char *) y1, 0, sizeof (y2));
+ memset (y, 0, sizeof (y) + 0);
+ memset (y1, 0, 0 + sizeof (y2));
+ memset ((void *) &c, 0, sizeof (&c));
+ memset ((signed char *) &c, 0, sizeof (&c));
+ memset (&c, 0, sizeof (&c) + 0);
+ memset (&c, 0, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ memcpy (y, x, sizeof (*y));
+ memcpy (y1, x, sizeof (*y2));
+ memcpy (buf1, x, sizeof buf1);
+ memcpy (buf3, x, sizeof (buf3));
+ memcpy (&buf3[0], x, sizeof (buf3));
+ memcpy (&buf4[0], x, sizeof (buf4));
+ memcpy (&y3, y, sizeof (y3));
+ memcpy ((char *) &y3, y, sizeof (y3));
+ memcpy (w, x, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy ((void *) y, x, sizeof (y));
+ memcpy ((char *) y1, x, sizeof (y2));
+ memcpy (y, x, sizeof (y) + 0);
+ memcpy (y1, x, 0 + sizeof (y2));
+ memcpy ((void *) &c, x, sizeof (&c));
+ memcpy ((signed char *) &c, x, sizeof (&c));
+ memcpy (&c, x, sizeof (&c) + 0);
+ memcpy (&c, x, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ memcpy (x, y, sizeof (*y));
+ memcpy (x, y1, sizeof (*y2));
+ memcpy (x, buf1, sizeof buf1);
+ memcpy (x, buf3, sizeof (buf3));
+ memcpy (x, &buf3[0], sizeof (buf3));
+ memcpy (x, &buf4[0], sizeof (buf4));
+ memcpy (y, &y3, sizeof (y3));
+ memcpy (y, (char *) &y3, sizeof (y3));
+ memcpy (x, w, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy (x, (void *) y, sizeof (y));
+ memcpy (x, (char *) y1, sizeof (y2));
+ memcpy (x, y, sizeof (y) + 0);
+ memcpy (x, y1, 0 + sizeof (y2));
+ memcpy (x, (void *) &c, sizeof (&c));
+ memcpy (x, (signed char *) &c, sizeof (&c));
+ memcpy (x, &c, sizeof (&c) + 0);
+ memcpy (x, &c, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ memmove (y, x, sizeof (*y));
+ memmove (y1, x, sizeof (*y2));
+ memmove (buf1, x, sizeof buf1);
+ memmove (buf3, x, sizeof (buf3));
+ memmove (&buf3[0], x, sizeof (buf3));
+ memmove (&buf4[0], x, sizeof (buf4));
+ memmove (&y3, y, sizeof (y3));
+ memmove ((char *) &y3, y, sizeof (y3));
+ memmove (w, x, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ memmove ((void *) y, x, sizeof (y));
+ memmove ((char *) y1, x, sizeof (y2));
+ memmove (y, x, sizeof (y) + 0);
+ memmove (y1, x, 0 + sizeof (y2));
+ memmove ((void *) &c, x, sizeof (&c));
+ memmove ((signed char *) &c, x, sizeof (&c));
+ memmove (&c, x, sizeof (&c) + 0);
+ memmove (&c, x, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ memmove (x, y, sizeof (*y));
+ memmove (x, y1, sizeof (*y2));
+ memmove (x, buf1, sizeof buf1);
+ memmove (x, buf3, sizeof (buf3));
+ memmove (x, &buf3[0], sizeof (buf3));
+ memmove (x, &buf4[0], sizeof (buf4));
+ memmove (y, &y3, sizeof (y3));
+ memmove (y, (char *) &y3, sizeof (y3));
+ memmove (x, w, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ memmove (x, (void *) y, sizeof (y));
+ memmove (x, (char *) y1, sizeof (y2));
+ memmove (x, y, sizeof (y) + 0);
+ memmove (x, y1, 0 + sizeof (y2));
+ memmove (x, (void *) &c, sizeof (&c));
+ memmove (x, (signed char *) &c, sizeof (&c));
+ memmove (x, &c, sizeof (&c) + 0);
+ memmove (x, &c, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ z += memcmp (y, x, sizeof (*y));
+ z += memcmp (y1, x, sizeof (*y2));
+ z += memcmp (buf1, x, sizeof buf1);
+ z += memcmp (buf3, x, sizeof (buf3));
+ z += memcmp (&buf3[0], x, sizeof (buf3));
+ z += memcmp (&buf4[0], x, sizeof (buf4));
+ z += memcmp (&y3, y, sizeof (y3));
+ z += memcmp ((char *) &y3, y, sizeof (y3));
+ z += memcmp (w, x, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp ((void *) y, x, sizeof (y));
+ z += memcmp ((char *) y1, x, sizeof (y2));
+ z += memcmp (y, x, sizeof (y) + 0);
+ z += memcmp (y1, x, 0 + sizeof (y2));
+ z += memcmp ((void *) &c, x, sizeof (&c));
+ z += memcmp ((signed char *) &c, x, sizeof (&c));
+ z += memcmp (&c, x, sizeof (&c) + 0);
+ z += memcmp (&c, x, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ z += memcmp (x, y, sizeof (*y));
+ z += memcmp (x, y1, sizeof (*y2));
+ z += memcmp (x, buf1, sizeof buf1);
+ z += memcmp (x, buf3, sizeof (buf3));
+ z += memcmp (x, &buf3[0], sizeof (buf3));
+ z += memcmp (x, &buf4[0], sizeof (buf4));
+ z += memcmp (y, &y3, sizeof (y3));
+ z += memcmp (y, (char *) &y3, sizeof (y3));
+ z += memcmp (x, w, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp (x, (void *) y, sizeof (y));
+ z += memcmp (x, (char *) y1, sizeof (y2));
+ z += memcmp (x, y, sizeof (y) + 0);
+ z += memcmp (x, y1, 0 + sizeof (y2));
+ z += memcmp (x, (void *) &c, sizeof (&c));
+ z += memcmp (x, (signed char *) &c, sizeof (&c));
+ z += memcmp (x, &c, sizeof (&c) + 0);
+ z += memcmp (x, &c, 0 + sizeof (&c));
+
+ return z;
+}
+
+template <int N>
+int
+f4 (char *x, char **y, int z)
+{
+ const char *s1 = "foobarbaz";
+ const char *s2 = "abcde12345678";
+ strncpy (x, s1, sizeof (s1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ strncat (x, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ y[0] = strndup (s1, sizeof (s1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ z += strncmp (s1, s2, sizeof (s1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ z += strncmp (s1, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ z += strncasecmp (s1, s2, sizeof (s1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ z += strncasecmp (s1, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+
+ // These are correct, no warning.
+ const char s3[] = "foobarbaz";
+ const char s4[] = "abcde12345678";
+ strncpy (x, s3, sizeof (s3));
+ strncat (x, s4, sizeof (s4));
+ y[1] = strndup (s3, sizeof (s3));
+ z += strncmp (s3, s4, sizeof (s3));
+ z += strncmp (s3, s4, sizeof (s4));
+ z += strncasecmp (s3, s4, sizeof (s3));
+ z += strncasecmp (s3, s4, sizeof (s4));
+
+ return z;
+}
+
+int
+f (void *x, char *y, int z, X w, char **u)
+{
+ z += f1<0> (x, z);
+ z += f2<0> (x, z);
+ z += f3<0> (x, y, z, w);
+ z += f4<0> (y, u, z);
+ return z;
+}
+
+// { dg-prune-output "\[\n\r\]*will always overflow\[\n\r\]*" }
--- gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C.jj 2012-08-16 14:00:00.843157082 +0200
+++ gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C 2012-08-16 13:59:44.000000000 +0200
@@ -0,0 +1,702 @@
+// Test -Wsizeof-pointer-memaccess warnings.
+// { dg-do compile }
+// { dg-options "-Wall" }
+// Test just twice, once with -O0 non-fortified, once with -O2 fortified.
+// { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } }
+// { dg-skip-if "" { *-*-* } { "-flto" } { "" } }
+
+extern "C" {
+
+typedef __SIZE_TYPE__ size_t;
+extern void *memset (void *, int, size_t);
+extern void *memcpy (void *__restrict, const void *__restrict, size_t);
+extern void *memmove (void *__restrict, const void *__restrict, size_t);
+extern int memcmp (const void *, const void *, size_t);
+extern char *strncpy (char *__restrict, const char *__restrict, size_t);
+extern char *strncat (char *__restrict, const char *__restrict, size_t);
+extern char *strndup (const char *, size_t);
+extern int strncmp (const char *, const char *, size_t);
+extern int strncasecmp (const char *, const char *, size_t);
+
+#ifdef __OPTIMIZE__
+# define bos(ptr) __builtin_object_size (ptr, 1)
+# define bos0(ptr) __builtin_object_size (ptr, 0)
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memset (void *dest, int c, size_t len)
+{
+ return __builtin___memset_chk (dest, c, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memcpy (void *__restrict dest, const void *__restrict src, size_t len)
+{
+ return __builtin___memcpy_chk (dest, src, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline void *
+memmove (void *dest, const void *src, size_t len)
+{
+ return __builtin___memmove_chk (dest, src, len, bos0 (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline char *
+strncpy (char *__restrict dest, const char *__restrict src, size_t len)
+{
+ return __builtin___strncpy_chk (dest, src, len, bos (dest));
+}
+
+__attribute__((__always_inline__, __gnu_inline__, __artificial__))
+extern inline char *
+strncat (char *dest, const char *src, size_t len)
+{
+ return __builtin___strncat_chk (dest, src, len, bos (dest));
+}
+#endif
+
+}
+
+struct A { short a, b; int c, d; long e, f; };
+typedef struct A TA;
+typedef struct A *PA;
+typedef TA *PTA;
+struct B {};
+typedef struct B TB;
+typedef struct B *PB;
+typedef TB *PTB;
+typedef int X[3][3][3];
+
+int
+f1 (void *x, int z)
+{
+ struct A a, *pa1 = &a;
+ TA *pa2 = &a;
+ PA pa3 = &a;
+ PTA pa4 = &a;
+ memset (&a, 0, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memset (pa1, 0, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pa2, 0, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pa3, 0, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pa4, 0, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pa1, 0, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pa2, 0, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pa3, 0, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pa4, 0, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memcpy (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memcpy (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pa1, x, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pa4, x, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memcpy (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memcpy (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pa1, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pa4, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ memmove (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memmove (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pa1, x, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pa4, x, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memmove (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memmove (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pa1, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pa4, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ z += memcmp (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ z += memcmp (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pa1, x, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ z += memcmp (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ z += memcmp (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pa1, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ // These are correct, no warning.
+ memset (&a, 0, sizeof a);
+ memset (&a, 0, sizeof (a));
+ memset (&a, 0, sizeof (struct A));
+ memset (&a, 0, sizeof (const struct A));
+ memset (&a, 0, sizeof (volatile struct A));
+ memset (&a, 0, sizeof (volatile const struct A));
+ memset (&a, 0, sizeof (TA));
+ memset (&a, 0, sizeof (__typeof (*&a)));
+ memset (pa1, 0, sizeof (*pa1));
+ memset (pa2, 0, sizeof (*pa3));
+ memset (pa3, 0, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ memset ((void *) &a, 0, sizeof (&a));
+ memset ((char *) &a, 0, sizeof (&a));
+ memset (&a, 0, sizeof (&a) + 0);
+ memset (&a, 0, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ memcpy (&a, x, sizeof a);
+ memcpy (&a, x, sizeof (a));
+ memcpy (&a, x, sizeof (struct A));
+ memcpy (&a, x, sizeof (const struct A));
+ memcpy (&a, x, sizeof (volatile struct A));
+ memcpy (&a, x, sizeof (volatile const struct A));
+ memcpy (&a, x, sizeof (TA));
+ memcpy (&a, x, sizeof (__typeof (*&a)));
+ memcpy (pa1, x, sizeof (*pa1));
+ memcpy (pa2, x, sizeof (*pa3));
+ memcpy (pa3, x, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy ((void *) &a, x, sizeof (&a));
+ memcpy ((char *) &a, x, sizeof (&a));
+ memcpy (&a, x, sizeof (&a) + 0);
+ memcpy (&a, x, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ memcpy (x, &a, sizeof a);
+ memcpy (x, &a, sizeof (a));
+ memcpy (x, &a, sizeof (struct A));
+ memcpy (x, &a, sizeof (const struct A));
+ memcpy (x, &a, sizeof (volatile struct A));
+ memcpy (x, &a, sizeof (volatile const struct A));
+ memcpy (x, &a, sizeof (TA));
+ memcpy (x, &a, sizeof (__typeof (*&a)));
+ memcpy (x, pa1, sizeof (*pa1));
+ memcpy (x, pa2, sizeof (*pa3));
+ memcpy (x, pa3, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy (x, (void *) &a, sizeof (&a));
+ memcpy (x, (char *) &a, sizeof (&a));
+ memcpy (x, &a, sizeof (&a) + 0);
+ memcpy (x, &a, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ memmove (&a, x, sizeof a);
+ memmove (&a, x, sizeof (a));
+ memmove (&a, x, sizeof (struct A));
+ memmove (&a, x, sizeof (const struct A));
+ memmove (&a, x, sizeof (volatile struct A));
+ memmove (&a, x, sizeof (volatile const struct A));
+ memmove (&a, x, sizeof (TA));
+ memmove (&a, x, sizeof (__typeof (*&a)));
+ memmove (pa1, x, sizeof (*pa1));
+ memmove (pa2, x, sizeof (*pa3));
+ memmove (pa3, x, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ memmove ((void *) &a, x, sizeof (&a));
+ memmove ((char *) &a, x, sizeof (&a));
+ memmove (&a, x, sizeof (&a) + 0);
+ memmove (&a, x, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ memmove (x, &a, sizeof a);
+ memmove (x, &a, sizeof (a));
+ memmove (x, &a, sizeof (struct A));
+ memmove (x, &a, sizeof (const struct A));
+ memmove (x, &a, sizeof (volatile struct A));
+ memmove (x, &a, sizeof (volatile const struct A));
+ memmove (x, &a, sizeof (TA));
+ memmove (x, &a, sizeof (__typeof (*&a)));
+ memmove (x, pa1, sizeof (*pa1));
+ memmove (x, pa2, sizeof (*pa3));
+ memmove (x, pa3, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ memmove (x, (void *) &a, sizeof (&a));
+ memmove (x, (char *) &a, sizeof (&a));
+ memmove (x, &a, sizeof (&a) + 0);
+ memmove (x, &a, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ z += memcmp (&a, x, sizeof a);
+ z += memcmp (&a, x, sizeof (a));
+ z += memcmp (&a, x, sizeof (struct A));
+ z += memcmp (&a, x, sizeof (const struct A));
+ z += memcmp (&a, x, sizeof (volatile struct A));
+ z += memcmp (&a, x, sizeof (volatile const struct A));
+ z += memcmp (&a, x, sizeof (TA));
+ z += memcmp (&a, x, sizeof (__typeof (*&a)));
+ z += memcmp (pa1, x, sizeof (*pa1));
+ z += memcmp (pa2, x, sizeof (*pa3));
+ z += memcmp (pa3, x, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp ((void *) &a, x, sizeof (&a));
+ z += memcmp ((char *) &a, x, sizeof (&a));
+ z += memcmp (&a, x, sizeof (&a) + 0);
+ z += memcmp (&a, x, 0 + sizeof (&a));
+
+ // These are correct, no warning.
+ z += memcmp (x, &a, sizeof a);
+ z += memcmp (x, &a, sizeof (a));
+ z += memcmp (x, &a, sizeof (struct A));
+ z += memcmp (x, &a, sizeof (const struct A));
+ z += memcmp (x, &a, sizeof (volatile struct A));
+ z += memcmp (x, &a, sizeof (volatile const struct A));
+ z += memcmp (x, &a, sizeof (TA));
+ z += memcmp (x, &a, sizeof (__typeof (*&a)));
+ z += memcmp (x, pa1, sizeof (*pa1));
+ z += memcmp (x, pa2, sizeof (*pa3));
+ z += memcmp (x, pa3, sizeof (__typeof (*pa3)));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp (x, (void *) &a, sizeof (&a));
+ z += memcmp (x, (char *) &a, sizeof (&a));
+ z += memcmp (x, &a, sizeof (&a) + 0);
+ z += memcmp (x, &a, 0 + sizeof (&a));
+
+ return z;
+}
+
+int
+f2 (void *x, int z)
+{
+ struct B b, *pb1 = &b;
+ TB *pb2 = &b;
+ PB pb3 = &b;
+ PTB pb4 = &b;
+ memset (&b, 0, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memset (pb1, 0, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pb2, 0, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pb3, 0, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pb4, 0, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memset (pb1, 0, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pb2, 0, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pb3, 0, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memset (pb4, 0, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memcpy (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memcpy (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memcpy (pb1, x, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memcpy (pb4, x, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memcpy (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memcpy (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memcpy (x, pb1, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memcpy (x, pb4, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ memmove (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memmove (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ memmove (pb1, x, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ memmove (pb4, x, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ memmove (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memmove (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ memmove (x, pb1, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ memmove (x, pb4, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ z += memcmp (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ z += memcmp (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+ z += memcmp (pb1, x, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" }
+
+ z += memcmp (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ z += memcmp (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+ z += memcmp (x, pb1, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+ z += memcmp (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" }
+
+ // These are correct, no warning.
+ memset (&b, 0, sizeof b);
+ memset (&b, 0, sizeof (b));
+ memset (&b, 0, sizeof (struct B));
+ memset (&b, 0, sizeof (const struct B));
+ memset (&b, 0, sizeof (volatile struct B));
+ memset (&b, 0, sizeof (volatile const struct B));
+ memset (&b, 0, sizeof (TB));
+ memset (&b, 0, sizeof (__typeof (*&b)));
+ memset (pb1, 0, sizeof (*pb1));
+ memset (pb2, 0, sizeof (*pb3));
+ memset (pb3, 0, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ memset ((void *) &b, 0, sizeof (&b));
+ memset ((char *) &b, 0, sizeof (&b));
+ memset (&b, 0, sizeof (&b) + 0);
+ memset (&b, 0, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ memcpy (&b, x, sizeof b);
+ memcpy (&b, x, sizeof (b));
+ memcpy (&b, x, sizeof (struct B));
+ memcpy (&b, x, sizeof (const struct B));
+ memcpy (&b, x, sizeof (volatile struct B));
+ memcpy (&b, x, sizeof (volatile const struct B));
+ memcpy (&b, x, sizeof (TB));
+ memcpy (&b, x, sizeof (__typeof (*&b)));
+ memcpy (pb1, x, sizeof (*pb1));
+ memcpy (pb2, x, sizeof (*pb3));
+ memcpy (pb3, x, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy ((void *) &b, x, sizeof (&b));
+ memcpy ((char *) &b, x, sizeof (&b));
+ memcpy (&b, x, sizeof (&b) + 0);
+ memcpy (&b, x, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ memcpy (x, &b, sizeof b);
+ memcpy (x, &b, sizeof (b));
+ memcpy (x, &b, sizeof (struct B));
+ memcpy (x, &b, sizeof (const struct B));
+ memcpy (x, &b, sizeof (volatile struct B));
+ memcpy (x, &b, sizeof (volatile const struct B));
+ memcpy (x, &b, sizeof (TB));
+ memcpy (x, &b, sizeof (__typeof (*&b)));
+ memcpy (x, pb1, sizeof (*pb1));
+ memcpy (x, pb2, sizeof (*pb3));
+ memcpy (x, pb3, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy (x, (void *) &b, sizeof (&b));
+ memcpy (x, (char *) &b, sizeof (&b));
+ memcpy (x, &b, sizeof (&b) + 0);
+ memcpy (x, &b, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ memmove (&b, x, sizeof b);
+ memmove (&b, x, sizeof (b));
+ memmove (&b, x, sizeof (struct B));
+ memmove (&b, x, sizeof (const struct B));
+ memmove (&b, x, sizeof (volatile struct B));
+ memmove (&b, x, sizeof (volatile const struct B));
+ memmove (&b, x, sizeof (TB));
+ memmove (&b, x, sizeof (__typeof (*&b)));
+ memmove (pb1, x, sizeof (*pb1));
+ memmove (pb2, x, sizeof (*pb3));
+ memmove (pb3, x, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ memmove ((void *) &b, x, sizeof (&b));
+ memmove ((char *) &b, x, sizeof (&b));
+ memmove (&b, x, sizeof (&b) + 0);
+ memmove (&b, x, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ memmove (x, &b, sizeof b);
+ memmove (x, &b, sizeof (b));
+ memmove (x, &b, sizeof (struct B));
+ memmove (x, &b, sizeof (const struct B));
+ memmove (x, &b, sizeof (volatile struct B));
+ memmove (x, &b, sizeof (volatile const struct B));
+ memmove (x, &b, sizeof (TB));
+ memmove (x, &b, sizeof (__typeof (*&b)));
+ memmove (x, pb1, sizeof (*pb1));
+ memmove (x, pb2, sizeof (*pb3));
+ memmove (x, pb3, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ memmove (x, (void *) &b, sizeof (&b));
+ memmove (x, (char *) &b, sizeof (&b));
+ memmove (x, &b, sizeof (&b) + 0);
+ memmove (x, &b, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ z += memcmp (&b, x, sizeof b);
+ z += memcmp (&b, x, sizeof (b));
+ z += memcmp (&b, x, sizeof (struct B));
+ z += memcmp (&b, x, sizeof (const struct B));
+ z += memcmp (&b, x, sizeof (volatile struct B));
+ z += memcmp (&b, x, sizeof (volatile const struct B));
+ z += memcmp (&b, x, sizeof (TB));
+ z += memcmp (&b, x, sizeof (__typeof (*&b)));
+ z += memcmp (pb1, x, sizeof (*pb1));
+ z += memcmp (pb2, x, sizeof (*pb3));
+ z += memcmp (pb3, x, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp ((void *) &b, x, sizeof (&b));
+ z += memcmp ((char *) &b, x, sizeof (&b));
+ z += memcmp (&b, x, sizeof (&b) + 0);
+ z += memcmp (&b, x, 0 + sizeof (&b));
+
+ // These are correct, no warning.
+ z += memcmp (x, &b, sizeof b);
+ z += memcmp (x, &b, sizeof (b));
+ z += memcmp (x, &b, sizeof (struct B));
+ z += memcmp (x, &b, sizeof (const struct B));
+ z += memcmp (x, &b, sizeof (volatile struct B));
+ z += memcmp (x, &b, sizeof (volatile const struct B));
+ z += memcmp (x, &b, sizeof (TB));
+ z += memcmp (x, &b, sizeof (__typeof (*&b)));
+ z += memcmp (x, pb1, sizeof (*pb1));
+ z += memcmp (x, pb2, sizeof (*pb3));
+ z += memcmp (x, pb3, sizeof (__typeof (*pb3)));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp (x, (void *) &b, sizeof (&b));
+ z += memcmp (x, (char *) &b, sizeof (&b));
+ z += memcmp (x, &b, sizeof (&b) + 0);
+ z += memcmp (x, &b, 0 + sizeof (&b));
+
+ return z;
+}
+
+int
+f3 (void *x, char *y, int z, X w)
+{
+ unsigned char *y1 = (unsigned char *) __builtin_alloca (z + 16);
+ char buf1[7];
+ signed char buf2[z + 32];
+ long buf3[17];
+ int *buf4[9];
+ signed char *y2 = buf2;
+ char c;
+ char *y3;
+ memset (y, 0, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memset (y1, 0, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memset (y2, 0, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memset (&c, 0, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memset (w, 0, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+ memcpy (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memcpy (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memcpy (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memcpy (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memcpy (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+ memcpy (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memcpy (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memcpy (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memcpy (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memcpy (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+ memmove (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memmove (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memmove (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ memmove (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ memmove (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+ memmove (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memmove (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memmove (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ memmove (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ memmove (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+ z += memcmp (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ z += memcmp (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ z += memcmp (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ z += memcmp (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" }
+ z += memcmp (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" }
+
+ z += memcmp (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ z += memcmp (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ z += memcmp (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ z += memcmp (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" }
+ z += memcmp (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" }
+
+ // These are correct, no warning.
+ memset (y, 0, sizeof (*y));
+ memset (y1, 0, sizeof (*y2));
+ memset (buf1, 0, sizeof buf1);
+ memset (buf3, 0, sizeof (buf3));
+ memset (&buf3[0], 0, sizeof (buf3));
+ memset (&buf4[0], 0, sizeof (buf4));
+ memset (w, 0, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ memset ((void *) y, 0, sizeof (y));
+ memset ((char *) y1, 0, sizeof (y2));
+ memset (y, 0, sizeof (y) + 0);
+ memset (y1, 0, 0 + sizeof (y2));
+ memset ((void *) &c, 0, sizeof (&c));
+ memset ((signed char *) &c, 0, sizeof (&c));
+ memset (&c, 0, sizeof (&c) + 0);
+ memset (&c, 0, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ memcpy (y, x, sizeof (*y));
+ memcpy (y1, x, sizeof (*y2));
+ memcpy (buf1, x, sizeof buf1);
+ memcpy (buf3, x, sizeof (buf3));
+ memcpy (&buf3[0], x, sizeof (buf3));
+ memcpy (&buf4[0], x, sizeof (buf4));
+ memcpy (&y3, y, sizeof (y3));
+ memcpy ((char *) &y3, y, sizeof (y3));
+ memcpy (w, x, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy ((void *) y, x, sizeof (y));
+ memcpy ((char *) y1, x, sizeof (y2));
+ memcpy (y, x, sizeof (y) + 0);
+ memcpy (y1, x, 0 + sizeof (y2));
+ memcpy ((void *) &c, x, sizeof (&c));
+ memcpy ((signed char *) &c, x, sizeof (&c));
+ memcpy (&c, x, sizeof (&c) + 0);
+ memcpy (&c, x, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ memcpy (x, y, sizeof (*y));
+ memcpy (x, y1, sizeof (*y2));
+ memcpy (x, buf1, sizeof buf1);
+ memcpy (x, buf3, sizeof (buf3));
+ memcpy (x, &buf3[0], sizeof (buf3));
+ memcpy (x, &buf4[0], sizeof (buf4));
+ memcpy (y, &y3, sizeof (y3));
+ memcpy (y, (char *) &y3, sizeof (y3));
+ memcpy (x, w, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ memcpy (x, (void *) y, sizeof (y));
+ memcpy (x, (char *) y1, sizeof (y2));
+ memcpy (x, y, sizeof (y) + 0);
+ memcpy (x, y1, 0 + sizeof (y2));
+ memcpy (x, (void *) &c, sizeof (&c));
+ memcpy (x, (signed char *) &c, sizeof (&c));
+ memcpy (x, &c, sizeof (&c) + 0);
+ memcpy (x, &c, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ memmove (y, x, sizeof (*y));
+ memmove (y1, x, sizeof (*y2));
+ memmove (buf1, x, sizeof buf1);
+ memmove (buf3, x, sizeof (buf3));
+ memmove (&buf3[0], x, sizeof (buf3));
+ memmove (&buf4[0], x, sizeof (buf4));
+ memmove (&y3, y, sizeof (y3));
+ memmove ((char *) &y3, y, sizeof (y3));
+ memmove (w, x, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ memmove ((void *) y, x, sizeof (y));
+ memmove ((char *) y1, x, sizeof (y2));
+ memmove (y, x, sizeof (y) + 0);
+ memmove (y1, x, 0 + sizeof (y2));
+ memmove ((void *) &c, x, sizeof (&c));
+ memmove ((signed char *) &c, x, sizeof (&c));
+ memmove (&c, x, sizeof (&c) + 0);
+ memmove (&c, x, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ memmove (x, y, sizeof (*y));
+ memmove (x, y1, sizeof (*y2));
+ memmove (x, buf1, sizeof buf1);
+ memmove (x, buf3, sizeof (buf3));
+ memmove (x, &buf3[0], sizeof (buf3));
+ memmove (x, &buf4[0], sizeof (buf4));
+ memmove (y, &y3, sizeof (y3));
+ memmove (y, (char *) &y3, sizeof (y3));
+ memmove (x, w, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ memmove (x, (void *) y, sizeof (y));
+ memmove (x, (char *) y1, sizeof (y2));
+ memmove (x, y, sizeof (y) + 0);
+ memmove (x, y1, 0 + sizeof (y2));
+ memmove (x, (void *) &c, sizeof (&c));
+ memmove (x, (signed char *) &c, sizeof (&c));
+ memmove (x, &c, sizeof (&c) + 0);
+ memmove (x, &c, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ z += memcmp (y, x, sizeof (*y));
+ z += memcmp (y1, x, sizeof (*y2));
+ z += memcmp (buf1, x, sizeof buf1);
+ z += memcmp (buf3, x, sizeof (buf3));
+ z += memcmp (&buf3[0], x, sizeof (buf3));
+ z += memcmp (&buf4[0], x, sizeof (buf4));
+ z += memcmp (&y3, y, sizeof (y3));
+ z += memcmp ((char *) &y3, y, sizeof (y3));
+ z += memcmp (w, x, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp ((void *) y, x, sizeof (y));
+ z += memcmp ((char *) y1, x, sizeof (y2));
+ z += memcmp (y, x, sizeof (y) + 0);
+ z += memcmp (y1, x, 0 + sizeof (y2));
+ z += memcmp ((void *) &c, x, sizeof (&c));
+ z += memcmp ((signed char *) &c, x, sizeof (&c));
+ z += memcmp (&c, x, sizeof (&c) + 0);
+ z += memcmp (&c, x, 0 + sizeof (&c));
+
+ // These are correct, no warning.
+ z += memcmp (x, y, sizeof (*y));
+ z += memcmp (x, y1, sizeof (*y2));
+ z += memcmp (x, buf1, sizeof buf1);
+ z += memcmp (x, buf3, sizeof (buf3));
+ z += memcmp (x, &buf3[0], sizeof (buf3));
+ z += memcmp (x, &buf4[0], sizeof (buf4));
+ z += memcmp (y, &y3, sizeof (y3));
+ z += memcmp (y, (char *) &y3, sizeof (y3));
+ z += memcmp (x, w, sizeof (X));
+ // These are probably broken, but obfuscated, no warning.
+ z += memcmp (x, (void *) y, sizeof (y));
+ z += memcmp (x, (char *) y1, sizeof (y2));
+ z += memcmp (x, y, sizeof (y) + 0);
+ z += memcmp (x, y1, 0 + sizeof (y2));
+ z += memcmp (x, (void *) &c, sizeof (&c));
+ z += memcmp (x, (signed char *) &c, sizeof (&c));
+ z += memcmp (x, &c, sizeof (&c) + 0);
+ z += memcmp (x, &c, 0 + sizeof (&c));
+
+ return z;
+}
+
+int
+f4 (char *x, char **y, int z)
+{
+ const char *s1 = "foobarbaz";
+ const char *s2 = "abcde12345678";
+ strncpy (x, s1, sizeof (s1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ strncat (x, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ y[0] = strndup (s1, sizeof (s1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ z += strncmp (s1, s2, sizeof (s1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ z += strncmp (s1, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+ z += strncasecmp (s1, s2, sizeof (s1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" }
+ z += strncasecmp (s1, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" }
+
+ // These are correct, no warning.
+ const char s3[] = "foobarbaz";
+ const char s4[] = "abcde12345678";
+ strncpy (x, s3, sizeof (s3));
+ strncat (x, s4, sizeof (s4));
+ y[1] = strndup (s3, sizeof (s3));
+ z += strncmp (s3, s4, sizeof (s3));
+ z += strncmp (s3, s4, sizeof (s4));
+ z += strncasecmp (s3, s4, sizeof (s3));
+ z += strncasecmp (s3, s4, sizeof (s4));
+
+ return z;
+}
+
+// { dg-prune-output "\[\n\r\]*will always overflow\[\n\r\]*" }
--- gcc/testsuite/g++.dg/ext/builtin30.C.jj 2012-08-16 15:35:44.573784210 +0200
+++ gcc/testsuite/g++.dg/ext/builtin30.C 2012-08-16 15:35:44.573784210 +0200
@@ -0,0 +1,27 @@
+// { dg-do compile }
+// { dg-options "-O2" }
+
+typedef __SIZE_TYPE__ size_t;
+extern "C" {
+extern void __chk_fail (void);
+extern int snprintf (char *, size_t, const char *, ...);
+extern inline __attribute__((gnu_inline, always_inline)) int snprintf (char *a, size_t b, const char *fmt, ...)
+{
+ if (__builtin_object_size (a, 0) != -1UL && __builtin_object_size (a, 0) < b)
+ __chk_fail ();
+ return __builtin_snprintf (a, b, fmt, __builtin_va_arg_pack ());
+}
+extern int snprintf (char *, size_t, const char *, ...) __asm ("mysnprintf");
+}
+
+char buf[10];
+
+int
+main (void)
+{
+ snprintf (buf, 10, "%d%d\n", 10, 10);
+ return 0;
+}
+
+// { dg-final { scan-assembler "mysnprintf" } }
+// { dg-final { scan-assembler-not "__chk_fail" } }
--- gcc/testsuite/gcc.dg/builtins-85.c.jj 2012-08-16 15:35:44.568784234 +0200
+++ gcc/testsuite/gcc.dg/builtins-85.c 2012-08-16 15:35:44.568784234 +0200
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef __SIZE_TYPE__ size_t;
+extern void __chk_fail (void);
+extern int snprintf (char *, size_t, const char *, ...);
+extern inline __attribute__((gnu_inline, always_inline)) int snprintf (char *a, size_t b, const char *fmt, ...)
+{
+ if (__builtin_object_size (a, 0) != -1UL && __builtin_object_size (a, 0) < b)
+ __chk_fail ();
+ return __builtin_snprintf (a, b, fmt, __builtin_va_arg_pack ());
+}
+extern int snprintf (char *, size_t, const char *, ...) __asm ("mysnprintf");
+
+char buf[10];
+
+int
+main (void)
+{
+ snprintf (buf, 10, "%d%d\n", 10, 10);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mysnprintf" } } */
+/* { dg-final { scan-assembler-not "__chk_fail" } } */
Jakub
More information about the Gcc-patches
mailing list