* [C++ PATCH] -Wsizeof-pointer-memaccess warning
@ 2012-08-16 19:20 Jakub Jelinek
2012-09-19 13:58 ` Jason Merrill
0 siblings, 1 reply; 10+ messages in thread
From: Jakub Jelinek @ 2012-08-16 19:20 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
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
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ PATCH] -Wsizeof-pointer-memaccess warning
2012-08-16 19:20 [C++ PATCH] -Wsizeof-pointer-memaccess warning Jakub Jelinek
@ 2012-09-19 13:58 ` Jason Merrill
2012-09-25 16:28 ` Jakub Jelinek
0 siblings, 1 reply; 10+ messages in thread
From: Jason Merrill @ 2012-09-19 13:58 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches
Hmm. This is a rather intrusive change to work around the problem of
early folding, which we'd like to move away from anyway. How does it
work to always keep SIZEOF_EXPR unfolded until cxx_eval_constant_expression?
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ PATCH] -Wsizeof-pointer-memaccess warning
2012-09-19 13:58 ` Jason Merrill
@ 2012-09-25 16:28 ` Jakub Jelinek
2012-10-02 12:57 ` [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2) Jakub Jelinek
0 siblings, 1 reply; 10+ messages in thread
From: Jakub Jelinek @ 2012-09-25 16:28 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
On Wed, Sep 19, 2012 at 09:57:51AM -0400, Jason Merrill wrote:
> Hmm. This is a rather intrusive change to work around the problem
> of early folding, which we'd like to move away from anyway. How
> does it work to always keep SIZEOF_EXPR unfolded until
> cxx_eval_constant_expression?
Ok, I've tried that, but it is getting uglier and uglier.
Here is the current patch. One issue already mentioned on IRC is
that generic code like contains_placeholder_p, save_expr etc.
got confused by SIZEOF_EXPR having type as argument instead of expression.
So for !processing_template_decl this patch uses instead NOP_EXPR with
error_mark_node operand and type on the NOP_EXPR, plus SIZEOF_EXPR_TYPE_P
bit set on the SIZEOF_EXPR (we need location on the sizeof expression, so
it should be expression). The patch solves that thing.
The remaining unsolved issues are two regressions, one is error
FAIL: g++.dg/warn/Wnull-conversion-1.C -std=gnu++98 (test for excess errors)
FAIL: g++.dg/warn/Wnull-conversion-1.C -std=gnu++11 (test for excess errors)
on the
int* r = sizeof(char) / 2;
line. Is that even valid C++11? C++03? The thing is that we previously
immediately folded sizeof(char) to 1, and 1/2 into 0 and considered that as
null_ptr_cst_p. With the patch we don't fold it anymore right away, we
have:
558 /* Core issue 903 says only literal 0 is a null pointer constant. */
559 if (cxx_dialect < cxx0x)
560 t = integral_constant_value (t);
in null_ptr_cst_p but guess we'd need to perform maybe_constant_value to
actually fold any SIZEOF_EXPRs in it into 0. Or use
fold_sizeof_expr_r (? if !TREE_SIDE_EFFECTS) like in
compute_array_index_type.
The other issue is Obj-C++ ICE, in cp_build_binary_op I've added
+ tree oop0 = maybe_constant_value (orig_op0);
+ tree oop1 = maybe_constant_value (orig_op1);
calls to make bootstrap possible (otherwise g++ would start warning about
if (read (...., sizeof (something)) != sizeof (something))
because one expression is signed while the other is unsigned (but we disable
that warning for small constants that fit into the other type, if
SIZEOF_EXPR isn't folded, we don't). Unfortunately, for Obj-C++, sometimes
orig_op0/orig_op1 contains ObjC specific tree codes like PROPERTY_REF, on
which cxx_eval_constant_expression ICEs:
7938 default:
7939 internal_error ("unexpected expression %qE of kind %s", t,
7940 tree_code_name[TREE_CODE (t)]);
7941 *non_constant_p = true;
No idea what to do about that unfortunately, we don't have any handy macro
to tell us the ObjC tree code range, we'd need to enumerate the Obj-C++ tree
codes which we don't want to ICE on (and just set *non_constant_p on them
instead). We have objc_is_property_ref predicate, but not sure about the
other ObjC trees.
Perhaps I should just revert that cp_build_binary_op change, but what to
replace it with?
2012-09-25 Jakub Jelinek <jakub@redhat.com>
cp/
* cp-tree.h (SIZEOF_EXPR_TYPE_P): Define.
* tree.c (cp_tree_equal): Handle SIZEOF_EXPR with
SIZEOF_EXPR_TYPE_P.
* mangle.c (write_expression): Likewise.
* cxx-pretty-print.c (pp_cxx_unary_expression): Likewise.
* error.c (dump_expr): Likewise.
* parser.c (cp_parser_unary_expression): For sizeof call
cxx_sizeof_or_alignof_{type,expr} just for diagnostics and
return SIZEOF_EXPR with the operand.
* pt.c (tsubst_copy, tsubst_copy_and_build): For SIZEOF_EXPR,
call cxx_sizeof_or_alignof_{type,expr} for diagnostics, but
return SIZEOF_EXPR with tsubsted operand.
(value_dependent_expression_p): Handle SIZEOF_EXPR with
SIZEOF_EXPR_TYPE_P.
(instantiation_dependent_r): Likewise.
* semantics.c (finish_call_expr): Call
sizeof_pointer_memaccess_warning if needed.
(cxx_eval_constant_expression): For SIZEOF_EXPR.
* decl.c (duplicate_decls): When redeclaring a builtin function,
keep the merged decl builtin also if newdecl is a gnu_inline
inline definition.
(fold_sizeof_expr_r): New function.
(compute_array_index_type): Fold SIZEOF_EXPRs in itype.
* cp-gimplify.c (cp_genericize_r): Fold SIZEOF_EXPR.
* typeck.c (cp_build_binary_op): For warn_for_sign_compare
try harder using maybe_constant_value to get INTEGER_CSTs.
* decl.c (stabilize_vla_size): Call pointer_set_destroy
at the end.
testsuite/
* g++.dg/torture/Wsizeof-pointer-memaccess1.C: New test.
* g++.dg/torture/Wsizeof-pointer-memaccess2.C: New test.
* g++.dg/warn/Wsign-compare-5.C: New test.
* g++.dg/warn/Wsizeof-pointer-memaccess-1.C: New test.
* g++.dg/ext/builtin30.C: New test.
* g++.dg/ext/vla12.C: New test.
* gcc.dg/builtins-85.c: New test.
libstdc++-v3/
* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust line
numbers.
--- gcc/cp/cp-tree.h.jj 2012-09-12 10:57:01.000000000 +0200
+++ gcc/cp/cp-tree.h 2012-09-24 19:36:27.946331084 +0200
@@ -79,6 +79,7 @@ c-common.h, not after.
OVL_ARG_DEPENDENT (in OVERLOAD)
PACK_EXPANSION_LOCAL_P (in *_PACK_EXPANSION)
TINFO_RECHECK_ACCESS_P (in TEMPLATE_INFO)
+ SIZEOF_EXPR_TYPE_P (in SIZEOF_EXPR)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
@@ -4044,6 +4045,10 @@ more_aggr_init_expr_args_p (const aggr_i
#define CONVERT_EXPR_VBASE_PATH(NODE) \
TREE_LANG_FLAG_0 (CONVERT_EXPR_CHECK (NODE))
+/* True if SIZEOF_EXPR argument is type. */
+#define SIZEOF_EXPR_TYPE_P(NODE) \
+ TREE_LANG_FLAG_0 (SIZEOF_EXPR_CHECK (NODE))
+
/* An enumeration of the kind of tags that C++ accepts. */
enum tag_types {
none_type = 0, /* Not a tag type. */
--- gcc/cp/cp-gimplify.c.jj 2012-09-14 14:20:55.000000000 +0200
+++ gcc/cp/cp-gimplify.c 2012-09-25 09:51:09.947883720 +0200
@@ -1119,6 +1119,22 @@ cp_genericize_r (tree *stmt_p, int *walk
genericize_break_stmt (stmt_p);
else if (TREE_CODE (stmt) == OMP_FOR)
genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
+ else if (TREE_CODE (stmt) == SIZEOF_EXPR)
+ {
+ if (SIZEOF_EXPR_TYPE_P (stmt))
+ *stmt_p
+ = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (stmt, 0)),
+ SIZEOF_EXPR, false);
+ else if (TYPE_P (TREE_OPERAND (stmt, 0)))
+ *stmt_p = cxx_sizeof_or_alignof_type (TREE_OPERAND (stmt, 0),
+ SIZEOF_EXPR, false);
+ else
+ *stmt_p = cxx_sizeof_or_alignof_expr (TREE_OPERAND (stmt, 0),
+ SIZEOF_EXPR, false);
+ if (*stmt_p == error_mark_node)
+ *stmt_p = size_one_node;
+ return NULL;
+ }
pointer_set_insert (p_set, *stmt_p);
--- gcc/cp/semantics.c.jj 2012-09-20 13:40:38.063143375 +0200
+++ gcc/cp/semantics.c 2012-09-25 09:52:26.125474643 +0200
@@ -2170,8 +2170,25 @@ 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
+ && !VEC_empty(tree, *args)
+ && TREE_CODE (VEC_last(tree, *args)) == SIZEOF_EXPR
+ && !processing_template_decl)
+ {
+ tree sizeof_arg = VEC_last(tree, *args);
+ if (SIZEOF_EXPR_TYPE_P (sizeof_arg))
+ sizeof_arg = TREE_TYPE (TREE_OPERAND (sizeof_arg, 0));
+ else
+ sizeof_arg = TREE_OPERAND (sizeof_arg, 0);
+ sizeof_pointer_memaccess_warning
+ (EXPR_LOCATION (VEC_last(tree, *args)), fn, *args,
+ sizeof_arg, 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)
{
@@ -7723,6 +7740,21 @@ cxx_eval_constant_expression (const cons
non_constant_p);
break;
+ case SIZEOF_EXPR:
+ if (SIZEOF_EXPR_TYPE_P (t))
+ r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
+ SIZEOF_EXPR, false);
+ else if (TYPE_P (TREE_OPERAND (t, 0)))
+ r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+ false);
+ else
+ r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+ false);
+ if (r == error_mark_node)
+ r = size_one_node;
+ VERIFY_CONSTANT (r);
+ break;
+
case COMPOUND_EXPR:
{
/* check_return_expr sometimes wraps a TARGET_EXPR in a
--- gcc/cp/tree.c.jj 2012-09-14 14:20:55.000000000 +0200
+++ gcc/cp/tree.c 2012-09-25 09:23:31.339552861 +0200
@@ -2602,6 +2602,10 @@ cp_tree_equal (tree t1, tree t2)
tree o1 = TREE_OPERAND (t1, 0);
tree o2 = TREE_OPERAND (t2, 0);
+ if (SIZEOF_EXPR_TYPE_P (t1))
+ o1 = TREE_TYPE (o1);
+ if (SIZEOF_EXPR_TYPE_P (t2))
+ o2 = TREE_TYPE (o2);
if (TREE_CODE (o1) != TREE_CODE (o2))
return false;
if (TYPE_P (o1))
--- gcc/cp/mangle.c.jj 2012-09-14 14:20:55.000000000 +0200
+++ gcc/cp/mangle.c 2012-09-25 09:26:58.019501621 +0200
@@ -2581,6 +2581,12 @@ write_expression (tree expr)
write_char ('E');
}
else if (TREE_CODE (expr) == SIZEOF_EXPR
+ && SIZEOF_EXPR_TYPE_P (expr))
+ {
+ write_string ("st");
+ write_type (TREE_TYPE (TREE_OPERAND (expr, 0)));
+ }
+ else if (TREE_CODE (expr) == SIZEOF_EXPR
&& TYPE_P (TREE_OPERAND (expr, 0)))
{
write_string ("st");
--- gcc/cp/decl.c.jj 2012-09-20 13:40:38.055143423 +0200
+++ gcc/cp/decl.c 2012-09-25 10:45:15.627068660 +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. */
@@ -7921,6 +7922,36 @@ stabilize_vla_size (tree size)
struct pointer_set_t *pset = pointer_set_create ();
/* Break out any function calls into temporary variables. */
cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
+ pointer_set_destroy (pset);
+}
+
+/* Helper function for compute_array_index_type. Look for SIZEOF_EXPR
+ not inside of SAVE_EXPR and fold them. */
+
+static tree
+fold_sizeof_expr_r (tree *expr_p, int *walk_subtrees, void *data)
+{
+ tree expr = *expr_p;
+ if (TREE_CODE (expr) == SAVE_EXPR || TYPE_P (expr))
+ *walk_subtrees = 0;
+ else if (TREE_CODE (expr) == SIZEOF_EXPR)
+ {
+ *(bool *)data = true;
+ if (SIZEOF_EXPR_TYPE_P (expr))
+ expr = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (expr, 0)),
+ SIZEOF_EXPR, false);
+ else if (TYPE_P (TREE_OPERAND (expr, 0)))
+ expr = cxx_sizeof_or_alignof_type (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
+ false);
+ else
+ expr = cxx_sizeof_or_alignof_expr (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
+ false);
+ if (expr == error_mark_node)
+ expr = size_one_node;
+ *expr_p = expr;
+ *walk_subtrees = 0;
+ }
+ return NULL;
}
/* Given the SIZE (i.e., number of elements) in an array, compute an
@@ -8116,8 +8147,21 @@ compute_array_index_type (tree name, tre
processing_template_decl = saved_processing_template_decl;
if (!TREE_CONSTANT (itype))
- /* A variable sized array. */
- itype = variable_size (itype);
+ {
+ /* A variable sized array. */
+ itype = variable_size (itype);
+ if (TREE_CODE (itype) != SAVE_EXPR)
+ {
+ /* Look for SIZEOF_EXPRs in itype and fold them, otherwise
+ they might survive till gimplification. */
+ tree newitype = itype;
+ bool found = false;
+ cp_walk_tree_without_duplicates (&newitype,
+ fold_sizeof_expr_r, &found);
+ if (found)
+ itype = variable_size (fold (newitype));
+ }
+ }
/* Make sure that there was no overflow when creating to a signed
index type. (For example, on a 32-bit machine, an array with
size 2^32 - 1 is too big.) */
--- gcc/cp/cxx-pretty-print.c.jj 2012-08-10 12:57:26.000000000 +0200
+++ gcc/cp/cxx-pretty-print.c 2012-09-24 19:20:59.846433758 +0200
@@ -798,7 +798,13 @@ pp_cxx_unary_expression (cxx_pretty_prin
case ALIGNOF_EXPR:
pp_cxx_ws_string (pp, code == SIZEOF_EXPR ? "sizeof" : "__alignof__");
pp_cxx_whitespace (pp);
- if (TYPE_P (TREE_OPERAND (t, 0)))
+ if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+ {
+ pp_cxx_left_paren (pp);
+ pp_cxx_type_id (pp, TREE_TYPE (TREE_OPERAND (t, 0)));
+ pp_cxx_right_paren (pp);
+ }
+ else if (TYPE_P (TREE_OPERAND (t, 0)))
{
pp_cxx_left_paren (pp);
pp_cxx_type_id (pp, TREE_OPERAND (t, 0));
--- gcc/cp/typeck.c.jj 2012-09-17 11:13:13.241074760 +0200
+++ gcc/cp/typeck.c 2012-09-25 09:22:16.334988243 +0200
@@ -4619,7 +4619,14 @@ cp_build_binary_op (location_t location,
&& !enum_cast_to_int (orig_op0)
&& !enum_cast_to_int (orig_op1))
{
- warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1,
+ tree oop0 = maybe_constant_value (orig_op0);
+ tree oop1 = maybe_constant_value (orig_op1);
+
+ if (TREE_CODE (oop0) != INTEGER_CST)
+ oop0 = orig_op0;
+ if (TREE_CODE (oop1) != INTEGER_CST)
+ oop1 = orig_op1;
+ warn_for_sign_compare (location, oop0, oop1, op0, op1,
result_type, resultcode);
}
}
--- gcc/cp/parser.c.jj 2012-09-20 13:40:38.044143486 +0200
+++ gcc/cp/parser.c 2012-09-25 09:21:16.881333051 +0200
@@ -6382,17 +6382,19 @@ cp_parser_unary_expression (cp_parser *p
case RID_ALIGNOF:
case RID_SIZEOF:
{
- tree operand;
+ tree operand, ret;
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 (TYPE_P (operand))
- return cxx_sizeof_or_alignof_type (operand, op, true);
+ ret = cxx_sizeof_or_alignof_type (operand, op, true);
else
{
/* ISO C++ defines alignof only with types, not with
@@ -6403,8 +6405,29 @@ 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);
+ ret = cxx_sizeof_or_alignof_expr (operand, op, true);
}
+ /* For SIZEOF_EXPR, just issue diagnostics, but keep
+ SIZEOF_EXPR with the original operand. */
+ if (op == SIZEOF_EXPR && ret != error_mark_node)
+ {
+ if (TREE_CODE (ret) != SIZEOF_EXPR || TYPE_P (operand))
+ {
+ if (!processing_template_decl && TYPE_P (operand))
+ {
+ ret = build_min (SIZEOF_EXPR, size_type_node,
+ build1 (NOP_EXPR, operand,
+ error_mark_node));
+ SIZEOF_EXPR_TYPE_P (ret) = 1;
+ }
+ else
+ ret = build_min (SIZEOF_EXPR, size_type_node, operand);
+ TREE_SIDE_EFFECTS (ret) = 0;
+ TREE_READONLY (ret) = 1;
+ }
+ SET_EXPR_LOCATION (ret, first_loc);
+ }
+ return ret;
}
case RID_NEW:
--- gcc/cp/pt.c.jj 2012-09-20 16:22:28.000000000 +0200
+++ gcc/cp/pt.c 2012-09-25 09:28:34.661048655 +0200
@@ -12031,14 +12031,16 @@ tsubst_copy (tree t, tree args, tsubst_f
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
{
- tree expanded;
+ tree expanded, op = TREE_OPERAND (t, 0);
int len = 0;
+ if (SIZEOF_EXPR_TYPE_P (t))
+ op = TREE_TYPE (op);
+
++cp_unevaluated_operand;
++c_inhibit_evaluation_warnings;
/* We only want to compute the number of arguments. */
- expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
- complain, in_decl);
+ expanded = tsubst_pack_expansion (op, args, complain, in_decl);
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
@@ -12065,6 +12067,16 @@ tsubst_copy (tree t, tree args, tsubst_f
else
return build_int_cst (size_type_node, len);
}
+ if (SIZEOF_EXPR_TYPE_P (t))
+ {
+ r = tsubst_copy (TREE_TYPE (TREE_OPERAND (t, 0)),
+ args, complain, in_decl);
+ r = build1 (NOP_EXPR, r, error_mark_node);
+ r = build1 (SIZEOF_EXPR,
+ tsubst (TREE_TYPE (t), args, complain, in_decl), r);
+ SIZEOF_EXPR_TYPE_P (r) = 1;
+ return r;
+ }
/* Fall through */
case INDIRECT_REF:
@@ -13468,31 +13480,56 @@ tsubst_copy_and_build (tree t,
/* Fall through */
case ALIGNOF_EXPR:
- op1 = TREE_OPERAND (t, 0);
- if (!args)
- {
- /* When there are no ARGS, we are trying to evaluate a
- non-dependent expression from the parser. Trying to do
- the substitutions may not work. */
- if (!TYPE_P (op1))
- op1 = TREE_TYPE (op1);
- }
- else
- {
- ++cp_unevaluated_operand;
- ++c_inhibit_evaluation_warnings;
- op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
- /*function_p=*/false,
- /*integral_constant_expression_p=*/false);
- --cp_unevaluated_operand;
- --c_inhibit_evaluation_warnings;
- }
- if (TYPE_P (op1))
- RETURN (cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
- complain & tf_error));
- else
- RETURN (cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
- complain & tf_error));
+ {
+ tree r;
+
+ op1 = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+ op1 = TREE_TYPE (op1);
+ if (!args)
+ {
+ /* When there are no ARGS, we are trying to evaluate a
+ non-dependent expression from the parser. Trying to do
+ the substitutions may not work. */
+ if (!TYPE_P (op1))
+ op1 = TREE_TYPE (op1);
+ }
+ else
+ {
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
+ op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/
+ false);
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
+ }
+ if (TYPE_P (op1))
+ r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
+ complain & tf_error);
+ else
+ r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
+ complain & tf_error);
+ if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node)
+ {
+ if (TREE_CODE (r) != SIZEOF_EXPR || TYPE_P (op1))
+ {
+ if (TYPE_P (op1))
+ {
+ r = build_min (SIZEOF_EXPR, size_type_node,
+ build1 (NOP_EXPR, op1, error_mark_node));
+ SIZEOF_EXPR_TYPE_P (r) = 1;
+ }
+ else
+ r = build_min (SIZEOF_EXPR, size_type_node, op1);
+ TREE_SIDE_EFFECTS (r) = 0;
+ TREE_READONLY (r) = 1;
+ }
+ SET_EXPR_LOCATION (r, EXPR_LOCATION (t));
+ }
+ RETURN (r);
+ }
case AT_ENCODE_EXPR:
{
@@ -19287,6 +19324,9 @@ value_dependent_expression_p (tree expre
}
case SIZEOF_EXPR:
+ if (SIZEOF_EXPR_TYPE_P (expression))
+ return dependent_type_p (TREE_TYPE (TREE_OPERAND (expression, 0)));
+ /* FALLTHRU */
case ALIGNOF_EXPR:
case TYPEID_EXPR:
/* A `sizeof' expression is value-dependent if the operand is
@@ -19626,6 +19666,8 @@ instantiation_dependent_r (tree *tp, int
case TRAIT_EXPR:
{
tree op = TREE_OPERAND (*tp, 0);
+ if (code == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (*tp))
+ op = TREE_TYPE (op);
if (TYPE_P (op))
{
if (dependent_type_p (op)
--- gcc/cp/error.c.jj 2012-09-14 14:20:55.000000000 +0200
+++ gcc/cp/error.c 2012-09-24 19:19:34.742901173 +0200
@@ -2312,7 +2312,9 @@ dump_expr (tree t, int flags)
}
pp_cxx_whitespace (cxx_pp);
pp_cxx_left_paren (cxx_pp);
- if (TYPE_P (TREE_OPERAND (t, 0)))
+ if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+ dump_type (TREE_TYPE (TREE_OPERAND (t, 0)), flags);
+ else if (TYPE_P (TREE_OPERAND (t, 0)))
dump_type (TREE_OPERAND (t, 0), flags);
else
dump_expr (TREE_OPERAND (t, 0), flags);
--- gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C.jj 2012-09-21 15:48:05.367214310 +0200
+++ gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C 2012-09-21 15:48:05.367214310 +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-09-21 15:48:05.368214305 +0200
+++ gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C 2012-09-21 15:48:05.368214305 +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/warn/Wsizeof-pointer-memaccess-1.C.jj 2012-09-25 11:25:38.593933892 +0200
+++ gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C 2012-09-25 11:25:04.000000000 +0200
@@ -0,0 +1,13 @@
+// Test -Wsizeof-pointer-memaccess warnings.
+// { dg-do compile }
+// { dg-options "-Wall" }
+
+typedef __SIZE_TYPE__ size_t;
+extern "C" void *memset (void *, int, size_t);
+
+int
+foo (int x, char b[10])
+{
+ long a[memset (b, 0, sizeof (b)) ? x + 10 : x]; // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length?" }
+ return a[0];
+}
--- gcc/testsuite/g++.dg/warn/Wsign-compare-5.C.jj 2012-09-24 17:07:26.190435596 +0200
+++ gcc/testsuite/g++.dg/warn/Wsign-compare-5.C 2012-09-24 17:07:17.000000000 +0200
@@ -0,0 +1,20 @@
+// Test that -Wsign-compare doesn't warn about
+// equality/non-equality comparisons with sizeof.
+// { dg-do compile }
+// { dg-options "-Wsign-compare" }
+
+int
+foo (int x)
+{
+ if (x != sizeof (sizeof (x))) // { dg-bogus "comparison between signed and unsigned integer expressions" }
+ return 1;
+ return 0;
+}
+
+int
+bar (int x)
+{
+ if (x == sizeof (sizeof (x)) + 1) // { dg-bogus "comparison between signed and unsigned integer expressions" }
+ return 1;
+ return 0;
+}
--- gcc/testsuite/g++.dg/ext/vla12.C.jj 2012-09-25 10:44:41.659254943 +0200
+++ gcc/testsuite/g++.dg/ext/vla12.C 2012-09-25 10:44:33.000000000 +0200
@@ -0,0 +1,28 @@
+// VLA sizeof test
+// { dg-do compile }
+// { dg-options "" }
+
+int
+f1 (int i)
+{
+ char a[sizeof (i) + 6 + i];
+ char b[sizeof (a) + 1];
+ return sizeof (b);
+}
+
+int
+f2 (int i)
+{
+ char a[sizeof (i) + 6 + i];
+ char b[sizeof (a)];
+ return sizeof (b);
+}
+
+int
+f3 (int i)
+{
+ char a[sizeof (i) + 6 + i];
+ char b[sizeof (i) + i];
+ char c[sizeof (a) + sizeof (b) + 7];
+ return sizeof (c);
+}
--- gcc/testsuite/g++.dg/ext/builtin30.C.jj 2012-09-21 15:48:05.375214264 +0200
+++ gcc/testsuite/g++.dg/ext/builtin30.C 2012-09-21 15:48:05.375214264 +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-09-21 15:48:05.375214264 +0200
+++ gcc/testsuite/gcc.dg/builtins-85.c 2012-09-21 15:48:05.375214264 +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" } } */
--- libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc.jj 2012-08-10 12:57:16.000000000 +0200
+++ libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc 2012-09-25 15:28:16.902924472 +0200
@@ -32,9 +32,9 @@ void test01()
{
X* px = 0;
std::shared_ptr<X> p1(px); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 776 }
+ // { dg-error "incomplete" "" { target *-*-* } 775 }
std::shared_ptr<X> p9(ap()); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 310 }
+ // { dg-error "incomplete" "" { target *-*-* } 307 }
}
Jakub
^ permalink raw reply [flat|nested] 10+ messages in thread
* [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2)
2012-09-25 16:28 ` Jakub Jelinek
@ 2012-10-02 12:57 ` Jakub Jelinek
2012-10-03 9:14 ` Dodji Seketeli
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Jakub Jelinek @ 2012-10-02 12:57 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
On Tue, Sep 25, 2012 at 05:36:40PM +0200, Jakub Jelinek wrote:
> Here is the current patch. One issue already mentioned on IRC is
> that generic code like contains_placeholder_p, save_expr etc.
> got confused by SIZEOF_EXPR having type as argument instead of expression.
> So for !processing_template_decl this patch uses instead NOP_EXPR with
> error_mark_node operand and type on the NOP_EXPR, plus SIZEOF_EXPR_TYPE_P
> bit set on the SIZEOF_EXPR (we need location on the sizeof expression, so
> it should be expression). The patch solves that thing.
>
> The remaining unsolved issues are two regressions, one is error
> FAIL: g++.dg/warn/Wnull-conversion-1.C -std=gnu++98 (test for excess errors)
> FAIL: g++.dg/warn/Wnull-conversion-1.C -std=gnu++11 (test for excess errors)
> on the
> int* r = sizeof(char) / 2;
> line. Is that even valid C++11? C++03? The thing is that we previously
> immediately folded sizeof(char) to 1, and 1/2 into 0 and considered that as
> null_ptr_cst_p. With the patch we don't fold it anymore right away, we
This patch uses maybe_constant_value for C++98/03, and makes the above an
error for C++11 (where the standard says that only literal 0 is null pointer
constant?).
> The other issue is Obj-C++ ICE, in cp_build_binary_op I've added
...
> No idea what to do about that unfortunately, we don't have any handy macro
> to tell us the ObjC tree code range, we'd need to enumerate the Obj-C++ tree
> codes which we don't want to ICE on (and just set *non_constant_p on them
> instead). We have objc_is_property_ref predicate, but not sure about the
> other ObjC trees.
And this is solved by saying objc_is_property_ref is not a
potential_constant_expression and removing the early return for C++98/03.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2012-10-02 Jakub Jelinek <jakub@redhat.com>
cp/
* cp-tree.h (SIZEOF_EXPR_TYPE_P): Define.
* tree.c (cp_tree_equal): Handle SIZEOF_EXPR with
SIZEOF_EXPR_TYPE_P.
* mangle.c (write_expression): Likewise.
* cxx-pretty-print.c (pp_cxx_unary_expression): Likewise.
* error.c (dump_expr): Likewise.
* parser.c (cp_parser_unary_expression): For sizeof call
cxx_sizeof_or_alignof_{type,expr} just for diagnostics and
return SIZEOF_EXPR with the operand.
* pt.c (tsubst_copy, tsubst_copy_and_build): For SIZEOF_EXPR,
call cxx_sizeof_or_alignof_{type,expr} for diagnostics, but
return SIZEOF_EXPR with tsubsted operand.
(value_dependent_expression_p): Handle SIZEOF_EXPR with
SIZEOF_EXPR_TYPE_P.
(instantiation_dependent_r): Likewise.
* call.c (null_ptr_cst_p): Call maybe_constant_value for C++98.
* semantics.c (finish_call_expr): Call
sizeof_pointer_memaccess_warning if needed.
(cxx_eval_constant_expression): Handle SIZEOF_EXPR.
(potential_constant_expression_1): Remove early exit for
C++98. Handle PROPERTY_REF.
* decl.c (duplicate_decls): When redeclaring a builtin function,
keep the merged decl builtin also if newdecl is a gnu_inline
inline definition.
(fold_sizeof_expr_r): New function.
(compute_array_index_type): Fold SIZEOF_EXPRs in itype.
* cp-gimplify.c (cp_genericize_r): Fold SIZEOF_EXPR.
* typeck.c (cp_build_binary_op): For warn_for_sign_compare
try harder using maybe_constant_value to get INTEGER_CSTs.
* decl.c (stabilize_vla_size): Call pointer_set_destroy
at the end.
testsuite/
* g++.dg/torture/Wsizeof-pointer-memaccess1.C: New test.
* g++.dg/torture/Wsizeof-pointer-memaccess2.C: New test.
* g++.dg/warn/Wsign-compare-5.C: New test.
* g++.dg/warn/Wsizeof-pointer-memaccess-1.C: New test.
* g++.dg/warn/Wnull-conversion-1.C: For c++11 add dg-error.
* g++.dg/ext/builtin30.C: New test.
* g++.dg/ext/vla12.C: New test.
* gcc.dg/builtins-85.c: New test.
libstdc++-v3/
* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust line
numbers.
--- gcc/cp/cp-tree.h.jj 2012-10-01 10:08:40.447237104 +0200
+++ gcc/cp/cp-tree.h 2012-10-01 17:38:18.506576783 +0200
@@ -79,6 +79,7 @@ c-common.h, not after.
OVL_ARG_DEPENDENT (in OVERLOAD)
PACK_EXPANSION_LOCAL_P (in *_PACK_EXPANSION)
TINFO_RECHECK_ACCESS_P (in TEMPLATE_INFO)
+ SIZEOF_EXPR_TYPE_P (in SIZEOF_EXPR)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
@@ -4044,6 +4045,10 @@ more_aggr_init_expr_args_p (const aggr_i
#define CONVERT_EXPR_VBASE_PATH(NODE) \
TREE_LANG_FLAG_0 (CONVERT_EXPR_CHECK (NODE))
+/* True if SIZEOF_EXPR argument is type. */
+#define SIZEOF_EXPR_TYPE_P(NODE) \
+ TREE_LANG_FLAG_0 (SIZEOF_EXPR_CHECK (NODE))
+
/* An enumeration of the kind of tags that C++ accepts. */
enum tag_types {
none_type = 0, /* Not a tag type. */
--- gcc/cp/cp-gimplify.c.jj 2012-09-27 12:45:49.060392494 +0200
+++ gcc/cp/cp-gimplify.c 2012-10-01 17:38:18.507576775 +0200
@@ -1119,6 +1119,22 @@ cp_genericize_r (tree *stmt_p, int *walk
genericize_break_stmt (stmt_p);
else if (TREE_CODE (stmt) == OMP_FOR)
genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
+ else if (TREE_CODE (stmt) == SIZEOF_EXPR)
+ {
+ if (SIZEOF_EXPR_TYPE_P (stmt))
+ *stmt_p
+ = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (stmt, 0)),
+ SIZEOF_EXPR, false);
+ else if (TYPE_P (TREE_OPERAND (stmt, 0)))
+ *stmt_p = cxx_sizeof_or_alignof_type (TREE_OPERAND (stmt, 0),
+ SIZEOF_EXPR, false);
+ else
+ *stmt_p = cxx_sizeof_or_alignof_expr (TREE_OPERAND (stmt, 0),
+ SIZEOF_EXPR, false);
+ if (*stmt_p == error_mark_node)
+ *stmt_p = size_one_node;
+ return NULL;
+ }
pointer_set_insert (p_set, *stmt_p);
--- gcc/cp/call.c.jj 2012-09-27 12:45:49.000000000 +0200
+++ gcc/cp/call.c 2012-10-01 17:53:17.594609236 +0200
@@ -557,7 +557,10 @@ null_ptr_cst_p (tree t)
{
/* Core issue 903 says only literal 0 is a null pointer constant. */
if (cxx_dialect < cxx0x)
- t = integral_constant_value (t);
+ {
+ t = integral_constant_value (t);
+ t = maybe_constant_value (t);
+ }
STRIP_NOPS (t);
if (integer_zerop (t) && !TREE_OVERFLOW (t))
return true;
--- gcc/cp/semantics.c.jj 2012-09-27 12:45:49.296391214 +0200
+++ gcc/cp/semantics.c 2012-10-01 17:50:27.088550744 +0200
@@ -2170,8 +2170,25 @@ 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
+ && !VEC_empty(tree, *args)
+ && TREE_CODE (VEC_last(tree, *args)) == SIZEOF_EXPR
+ && !processing_template_decl)
+ {
+ tree sizeof_arg = VEC_last(tree, *args);
+ if (SIZEOF_EXPR_TYPE_P (sizeof_arg))
+ sizeof_arg = TREE_TYPE (TREE_OPERAND (sizeof_arg, 0));
+ else
+ sizeof_arg = TREE_OPERAND (sizeof_arg, 0);
+ sizeof_pointer_memaccess_warning
+ (EXPR_LOCATION (VEC_last(tree, *args)), fn, *args,
+ sizeof_arg, 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)
{
@@ -7723,6 +7740,21 @@ cxx_eval_constant_expression (const cons
non_constant_p);
break;
+ case SIZEOF_EXPR:
+ if (SIZEOF_EXPR_TYPE_P (t))
+ r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
+ SIZEOF_EXPR, false);
+ else if (TYPE_P (TREE_OPERAND (t, 0)))
+ r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+ false);
+ else
+ r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+ false);
+ if (r == error_mark_node)
+ r = size_one_node;
+ VERIFY_CONSTANT (r);
+ break;
+
case COMPOUND_EXPR:
{
/* check_return_expr sometimes wraps a TARGET_EXPR in a
@@ -8106,12 +8138,6 @@ potential_constant_expression_1 (tree t,
int i;
tree tmp;
- /* C++98 has different rules for the form of a constant expression that
- are enforced in the parser, so we can assume that anything that gets
- this far is suitable. */
- if (cxx_dialect < cxx0x)
- return true;
-
if (t == error_mark_node)
return false;
if (t == NULL_TREE)
@@ -8632,6 +8658,9 @@ potential_constant_expression_1 (tree t,
return false;
default:
+ if (objc_is_property_ref (t))
+ return false;
+
sorry ("unexpected AST of kind %s", tree_code_name[TREE_CODE (t)]);
gcc_unreachable();
return false;
--- gcc/cp/tree.c.jj 2012-09-27 12:45:49.083392369 +0200
+++ gcc/cp/tree.c 2012-10-01 17:38:18.512576744 +0200
@@ -2602,6 +2602,10 @@ cp_tree_equal (tree t1, tree t2)
tree o1 = TREE_OPERAND (t1, 0);
tree o2 = TREE_OPERAND (t2, 0);
+ if (SIZEOF_EXPR_TYPE_P (t1))
+ o1 = TREE_TYPE (o1);
+ if (SIZEOF_EXPR_TYPE_P (t2))
+ o2 = TREE_TYPE (o2);
if (TREE_CODE (o1) != TREE_CODE (o2))
return false;
if (TYPE_P (o1))
--- gcc/cp/mangle.c.jj 2012-09-27 12:45:49.111392217 +0200
+++ gcc/cp/mangle.c 2012-10-01 17:38:18.513576740 +0200
@@ -2581,6 +2581,12 @@ write_expression (tree expr)
write_char ('E');
}
else if (TREE_CODE (expr) == SIZEOF_EXPR
+ && SIZEOF_EXPR_TYPE_P (expr))
+ {
+ write_string ("st");
+ write_type (TREE_TYPE (TREE_OPERAND (expr, 0)));
+ }
+ else if (TREE_CODE (expr) == SIZEOF_EXPR
&& TYPE_P (TREE_OPERAND (expr, 0)))
{
write_string ("st");
--- gcc/cp/decl.c.jj 2012-10-01 10:08:40.429237206 +0200
+++ gcc/cp/decl.c 2012-10-01 17:38:18.516576724 +0200
@@ -2160,39 +2160,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. */
@@ -7928,6 +7929,36 @@ stabilize_vla_size (tree size)
struct pointer_set_t *pset = pointer_set_create ();
/* Break out any function calls into temporary variables. */
cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
+ pointer_set_destroy (pset);
+}
+
+/* Helper function for compute_array_index_type. Look for SIZEOF_EXPR
+ not inside of SAVE_EXPR and fold them. */
+
+static tree
+fold_sizeof_expr_r (tree *expr_p, int *walk_subtrees, void *data)
+{
+ tree expr = *expr_p;
+ if (TREE_CODE (expr) == SAVE_EXPR || TYPE_P (expr))
+ *walk_subtrees = 0;
+ else if (TREE_CODE (expr) == SIZEOF_EXPR)
+ {
+ *(bool *)data = true;
+ if (SIZEOF_EXPR_TYPE_P (expr))
+ expr = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (expr, 0)),
+ SIZEOF_EXPR, false);
+ else if (TYPE_P (TREE_OPERAND (expr, 0)))
+ expr = cxx_sizeof_or_alignof_type (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
+ false);
+ else
+ expr = cxx_sizeof_or_alignof_expr (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
+ false);
+ if (expr == error_mark_node)
+ expr = size_one_node;
+ *expr_p = expr;
+ *walk_subtrees = 0;
+ }
+ return NULL;
}
/* Given the SIZE (i.e., number of elements) in an array, compute an
@@ -8123,8 +8154,21 @@ compute_array_index_type (tree name, tre
processing_template_decl = saved_processing_template_decl;
if (!TREE_CONSTANT (itype))
- /* A variable sized array. */
- itype = variable_size (itype);
+ {
+ /* A variable sized array. */
+ itype = variable_size (itype);
+ if (TREE_CODE (itype) != SAVE_EXPR)
+ {
+ /* Look for SIZEOF_EXPRs in itype and fold them, otherwise
+ they might survive till gimplification. */
+ tree newitype = itype;
+ bool found = false;
+ cp_walk_tree_without_duplicates (&newitype,
+ fold_sizeof_expr_r, &found);
+ if (found)
+ itype = variable_size (fold (newitype));
+ }
+ }
/* Make sure that there was no overflow when creating to a signed
index type. (For example, on a 32-bit machine, an array with
size 2^32 - 1 is too big.) */
--- gcc/cp/cxx-pretty-print.c.jj 2012-09-27 12:45:49.118392179 +0200
+++ gcc/cp/cxx-pretty-print.c 2012-10-01 17:38:18.518576711 +0200
@@ -798,7 +798,13 @@ pp_cxx_unary_expression (cxx_pretty_prin
case ALIGNOF_EXPR:
pp_cxx_ws_string (pp, code == SIZEOF_EXPR ? "sizeof" : "__alignof__");
pp_cxx_whitespace (pp);
- if (TYPE_P (TREE_OPERAND (t, 0)))
+ if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+ {
+ pp_cxx_left_paren (pp);
+ pp_cxx_type_id (pp, TREE_TYPE (TREE_OPERAND (t, 0)));
+ pp_cxx_right_paren (pp);
+ }
+ else if (TYPE_P (TREE_OPERAND (t, 0)))
{
pp_cxx_left_paren (pp);
pp_cxx_type_id (pp, TREE_OPERAND (t, 0));
--- gcc/cp/typeck.c.jj 2012-09-27 12:45:49.208391691 +0200
+++ gcc/cp/typeck.c 2012-10-01 17:38:18.519576704 +0200
@@ -4624,7 +4624,14 @@ cp_build_binary_op (location_t location,
&& !enum_cast_to_int (orig_op0)
&& !enum_cast_to_int (orig_op1))
{
- warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1,
+ tree oop0 = maybe_constant_value (orig_op0);
+ tree oop1 = maybe_constant_value (orig_op1);
+
+ if (TREE_CODE (oop0) != INTEGER_CST)
+ oop0 = orig_op0;
+ if (TREE_CODE (oop1) != INTEGER_CST)
+ oop1 = orig_op1;
+ warn_for_sign_compare (location, oop0, oop1, op0, op1,
result_type, resultcode);
}
}
--- gcc/cp/parser.c.jj 2012-10-01 10:08:40.447237104 +0200
+++ gcc/cp/parser.c 2012-10-01 17:38:18.524576680 +0200
@@ -6383,17 +6383,19 @@ cp_parser_unary_expression (cp_parser *p
case RID_ALIGNOF:
case RID_SIZEOF:
{
- tree operand;
+ tree operand, ret;
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 (TYPE_P (operand))
- return cxx_sizeof_or_alignof_type (operand, op, true);
+ ret = cxx_sizeof_or_alignof_type (operand, op, true);
else
{
/* ISO C++ defines alignof only with types, not with
@@ -6404,8 +6406,29 @@ 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);
+ ret = cxx_sizeof_or_alignof_expr (operand, op, true);
}
+ /* For SIZEOF_EXPR, just issue diagnostics, but keep
+ SIZEOF_EXPR with the original operand. */
+ if (op == SIZEOF_EXPR && ret != error_mark_node)
+ {
+ if (TREE_CODE (ret) != SIZEOF_EXPR || TYPE_P (operand))
+ {
+ if (!processing_template_decl && TYPE_P (operand))
+ {
+ ret = build_min (SIZEOF_EXPR, size_type_node,
+ build1 (NOP_EXPR, operand,
+ error_mark_node));
+ SIZEOF_EXPR_TYPE_P (ret) = 1;
+ }
+ else
+ ret = build_min (SIZEOF_EXPR, size_type_node, operand);
+ TREE_SIDE_EFFECTS (ret) = 0;
+ TREE_READONLY (ret) = 1;
+ }
+ SET_EXPR_LOCATION (ret, first_loc);
+ }
+ return ret;
}
case RID_NEW:
--- gcc/cp/pt.c.jj 2012-10-01 10:08:40.445237116 +0200
+++ gcc/cp/pt.c 2012-10-01 17:38:18.529576651 +0200
@@ -12031,14 +12031,16 @@ tsubst_copy (tree t, tree args, tsubst_f
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
{
- tree expanded;
+ tree expanded, op = TREE_OPERAND (t, 0);
int len = 0;
+ if (SIZEOF_EXPR_TYPE_P (t))
+ op = TREE_TYPE (op);
+
++cp_unevaluated_operand;
++c_inhibit_evaluation_warnings;
/* We only want to compute the number of arguments. */
- expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
- complain, in_decl);
+ expanded = tsubst_pack_expansion (op, args, complain, in_decl);
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
@@ -12065,6 +12067,16 @@ tsubst_copy (tree t, tree args, tsubst_f
else
return build_int_cst (size_type_node, len);
}
+ if (SIZEOF_EXPR_TYPE_P (t))
+ {
+ r = tsubst_copy (TREE_TYPE (TREE_OPERAND (t, 0)),
+ args, complain, in_decl);
+ r = build1 (NOP_EXPR, r, error_mark_node);
+ r = build1 (SIZEOF_EXPR,
+ tsubst (TREE_TYPE (t), args, complain, in_decl), r);
+ SIZEOF_EXPR_TYPE_P (r) = 1;
+ return r;
+ }
/* Fall through */
case INDIRECT_REF:
@@ -13468,31 +13480,56 @@ tsubst_copy_and_build (tree t,
/* Fall through */
case ALIGNOF_EXPR:
- op1 = TREE_OPERAND (t, 0);
- if (!args)
- {
- /* When there are no ARGS, we are trying to evaluate a
- non-dependent expression from the parser. Trying to do
- the substitutions may not work. */
- if (!TYPE_P (op1))
- op1 = TREE_TYPE (op1);
- }
- else
- {
- ++cp_unevaluated_operand;
- ++c_inhibit_evaluation_warnings;
- op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
- /*function_p=*/false,
- /*integral_constant_expression_p=*/false);
- --cp_unevaluated_operand;
- --c_inhibit_evaluation_warnings;
- }
- if (TYPE_P (op1))
- RETURN (cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
- complain & tf_error));
- else
- RETURN (cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
- complain & tf_error));
+ {
+ tree r;
+
+ op1 = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+ op1 = TREE_TYPE (op1);
+ if (!args)
+ {
+ /* When there are no ARGS, we are trying to evaluate a
+ non-dependent expression from the parser. Trying to do
+ the substitutions may not work. */
+ if (!TYPE_P (op1))
+ op1 = TREE_TYPE (op1);
+ }
+ else
+ {
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
+ op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/
+ false);
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
+ }
+ if (TYPE_P (op1))
+ r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
+ complain & tf_error);
+ else
+ r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
+ complain & tf_error);
+ if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node)
+ {
+ if (TREE_CODE (r) != SIZEOF_EXPR || TYPE_P (op1))
+ {
+ if (TYPE_P (op1))
+ {
+ r = build_min (SIZEOF_EXPR, size_type_node,
+ build1 (NOP_EXPR, op1, error_mark_node));
+ SIZEOF_EXPR_TYPE_P (r) = 1;
+ }
+ else
+ r = build_min (SIZEOF_EXPR, size_type_node, op1);
+ TREE_SIDE_EFFECTS (r) = 0;
+ TREE_READONLY (r) = 1;
+ }
+ SET_EXPR_LOCATION (r, EXPR_LOCATION (t));
+ }
+ RETURN (r);
+ }
case AT_ENCODE_EXPR:
{
@@ -19288,6 +19325,9 @@ value_dependent_expression_p (tree expre
}
case SIZEOF_EXPR:
+ if (SIZEOF_EXPR_TYPE_P (expression))
+ return dependent_type_p (TREE_TYPE (TREE_OPERAND (expression, 0)));
+ /* FALLTHRU */
case ALIGNOF_EXPR:
case TYPEID_EXPR:
/* A `sizeof' expression is value-dependent if the operand is
@@ -19627,6 +19667,8 @@ instantiation_dependent_r (tree *tp, int
case TRAIT_EXPR:
{
tree op = TREE_OPERAND (*tp, 0);
+ if (code == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (*tp))
+ op = TREE_TYPE (op);
if (TYPE_P (op))
{
if (dependent_type_p (op)
--- gcc/cp/error.c.jj 2012-09-27 12:45:49.151391999 +0200
+++ gcc/cp/error.c 2012-10-01 17:38:18.532576635 +0200
@@ -2312,7 +2312,9 @@ dump_expr (tree t, int flags)
}
pp_cxx_whitespace (cxx_pp);
pp_cxx_left_paren (cxx_pp);
- if (TYPE_P (TREE_OPERAND (t, 0)))
+ if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+ dump_type (TREE_TYPE (TREE_OPERAND (t, 0)), flags);
+ else if (TYPE_P (TREE_OPERAND (t, 0)))
dump_type (TREE_OPERAND (t, 0), flags);
else
dump_expr (TREE_OPERAND (t, 0), flags);
--- gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C.jj 2012-10-01 17:38:18.549576540 +0200
+++ gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C 2012-10-01 17:38:18.549576540 +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-10-01 17:38:18.549576540 +0200
+++ gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C 2012-10-01 17:38:18.549576540 +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/warn/Wsizeof-pointer-memaccess-1.C.jj 2012-10-01 17:38:18.556576500 +0200
+++ gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C 2012-10-01 17:38:18.556576500 +0200
@@ -0,0 +1,13 @@
+// Test -Wsizeof-pointer-memaccess warnings.
+// { dg-do compile }
+// { dg-options "-Wall" }
+
+typedef __SIZE_TYPE__ size_t;
+extern "C" void *memset (void *, int, size_t);
+
+int
+foo (int x, char b[10])
+{
+ long a[memset (b, 0, sizeof (b)) ? x + 10 : x]; // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length?" }
+ return a[0];
+}
--- gcc/testsuite/g++.dg/warn/Wsign-compare-5.C.jj 2012-10-01 17:38:18.556576500 +0200
+++ gcc/testsuite/g++.dg/warn/Wsign-compare-5.C 2012-10-01 17:38:18.556576500 +0200
@@ -0,0 +1,20 @@
+// Test that -Wsign-compare doesn't warn about
+// equality/non-equality comparisons with sizeof.
+// { dg-do compile }
+// { dg-options "-Wsign-compare" }
+
+int
+foo (int x)
+{
+ if (x != sizeof (sizeof (x))) // { dg-bogus "comparison between signed and unsigned integer expressions" }
+ return 1;
+ return 0;
+}
+
+int
+bar (int x)
+{
+ if (x == sizeof (sizeof (x)) + 1) // { dg-bogus "comparison between signed and unsigned integer expressions" }
+ return 1;
+ return 0;
+}
--- gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C.jj 2011-05-02 18:39:10.000000000 +0200
+++ gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C 2012-10-02 10:32:08.764195850 +0200
@@ -9,7 +9,7 @@ void func2() {
int* t = false; // { dg-warning "converting 'false' to pointer" }
int* p;
p = false; // { dg-warning "converting 'false' to pointer" }
- int* r = sizeof(char) / 2;
+ int* r = sizeof(char) / 2; // { dg-error "invalid conversion from" "" { target c++11 } }
func1(false); // { dg-warning "converting 'false' to pointer" }
int i = NULL; // { dg-warning "converting to non-pointer" }
}
--- gcc/testsuite/g++.dg/ext/vla12.C.jj 2012-10-01 17:38:18.556576500 +0200
+++ gcc/testsuite/g++.dg/ext/vla12.C 2012-10-01 17:38:18.557576495 +0200
@@ -0,0 +1,28 @@
+// VLA sizeof test
+// { dg-do compile }
+// { dg-options "" }
+
+int
+f1 (int i)
+{
+ char a[sizeof (i) + 6 + i];
+ char b[sizeof (a) + 1];
+ return sizeof (b);
+}
+
+int
+f2 (int i)
+{
+ char a[sizeof (i) + 6 + i];
+ char b[sizeof (a)];
+ return sizeof (b);
+}
+
+int
+f3 (int i)
+{
+ char a[sizeof (i) + 6 + i];
+ char b[sizeof (i) + i];
+ char c[sizeof (a) + sizeof (b) + 7];
+ return sizeof (c);
+}
--- gcc/testsuite/g++.dg/ext/builtin30.C.jj 2012-10-01 17:38:18.557576495 +0200
+++ gcc/testsuite/g++.dg/ext/builtin30.C 2012-10-01 17:38:18.557576495 +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-10-01 17:38:18.557576495 +0200
+++ gcc/testsuite/gcc.dg/builtins-85.c 2012-10-01 17:38:18.557576495 +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" } } */
--- libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc.jj 2012-08-10 12:57:16.000000000 +0200
+++ libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc 2012-09-25 15:28:16.902924472 +0200
@@ -32,9 +32,9 @@ void test01()
{
X* px = 0;
std::shared_ptr<X> p1(px); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 776 }
+ // { dg-error "incomplete" "" { target *-*-* } 775 }
std::shared_ptr<X> p9(ap()); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 310 }
+ // { dg-error "incomplete" "" { target *-*-* } 307 }
}
Jakub
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2)
2012-10-02 12:57 ` [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2) Jakub Jelinek
@ 2012-10-03 9:14 ` Dodji Seketeli
2012-10-03 9:43 ` Jakub Jelinek
2012-10-05 13:45 ` Jason Merrill
` (2 subsequent siblings)
3 siblings, 1 reply; 10+ messages in thread
From: Dodji Seketeli @ 2012-10-03 9:14 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Jason Merrill, gcc-patches
Jakub Jelinek <jakub@redhat.com> a écrit:
> --- gcc/cp/call.c.jj 2012-09-27 12:45:49.000000000 +0200
> +++ gcc/cp/call.c 2012-10-01 17:53:17.594609236 +0200
> @@ -557,7 +557,10 @@ null_ptr_cst_p (tree t)
> {
> /* Core issue 903 says only literal 0 is a null pointer constant. */
> if (cxx_dialect < cxx0x)
> - t = integral_constant_value (t);
> + {
> + t = integral_constant_value (t);
> + t = maybe_constant_value (t);
> + }
Just for my education, why couldn't maybe_constant_value just call
integral_constant_value, so that we just use maybe_constant_value here?
Even after reading the comments of these two functions, /having/ to use
them like this seems confusing to the casual reader in me.
--
Dodji
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2)
2012-10-03 9:14 ` Dodji Seketeli
@ 2012-10-03 9:43 ` Jakub Jelinek
0 siblings, 0 replies; 10+ messages in thread
From: Jakub Jelinek @ 2012-10-03 9:43 UTC (permalink / raw)
To: Dodji Seketeli; +Cc: Jason Merrill, gcc-patches
On Wed, Oct 03, 2012 at 11:14:37AM +0200, Dodji Seketeli wrote:
> Jakub Jelinek <jakub@redhat.com> a écrit:
>
> > --- gcc/cp/call.c.jj 2012-09-27 12:45:49.000000000 +0200
> > +++ gcc/cp/call.c 2012-10-01 17:53:17.594609236 +0200
> > @@ -557,7 +557,10 @@ null_ptr_cst_p (tree t)
> > {
> > /* Core issue 903 says only literal 0 is a null pointer constant. */
> > if (cxx_dialect < cxx0x)
> > - t = integral_constant_value (t);
> > + {
> > + t = integral_constant_value (t);
> > + t = maybe_constant_value (t);
> > + }
>
> Just for my education, why couldn't maybe_constant_value just call
> integral_constant_value, so that we just use maybe_constant_value here?
Perhaps maybe_constant_value already does all that integral_constant_value
does, but I'm not sure about it. maybe_constant_value starts with a lot of
conditions where it doesn't do anything if they are true,
integral_constant_value doesn't have any such conditions, on the other side
performs far less - just loops through DECL_INITIAL values looking for a
const. As I said earlier, while the initial hacks around early folding
of SIZEOF_EXPR were quite ugly, the amount of changes to allow late folding
of SIZEOF_EXPR was huge, with user visible changes etc.
Jakub
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2)
2012-10-02 12:57 ` [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2) Jakub Jelinek
2012-10-03 9:14 ` Dodji Seketeli
@ 2012-10-05 13:45 ` Jason Merrill
2012-10-11 0:41 ` Hans-Peter Nilsson
2012-10-26 13:36 ` [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2) Roman Zhuykov
3 siblings, 0 replies; 10+ messages in thread
From: Jason Merrill @ 2012-10-05 13:45 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches
On 10/02/2012 08:56 AM, Jakub Jelinek wrote:
> Perhaps maybe_constant_value already does all that integral_constant_value
> does, but I'm not sure about it.
It does, you can remove that call.
OK with that change.
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2)
2012-10-02 12:57 ` [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2) Jakub Jelinek
2012-10-03 9:14 ` Dodji Seketeli
2012-10-05 13:45 ` Jason Merrill
@ 2012-10-11 0:41 ` Hans-Peter Nilsson
2012-10-11 11:54 ` Committed, PR54897 (was: [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2)) Hans-Peter Nilsson
2012-10-26 13:36 ` [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2) Roman Zhuykov
3 siblings, 1 reply; 10+ messages in thread
From: Hans-Peter Nilsson @ 2012-10-11 0:41 UTC (permalink / raw)
To: jakub; +Cc: jason, gcc-patches
> From: Jakub Jelinek <jakub@redhat.com>
> Date: Tue, 2 Oct 2012 14:56:29 +0200
> 2012-10-02 Jakub Jelinek <jakub@redhat.com>
>
> cp/
> * cp-tree.h (SIZEOF_EXPR_TYPE_P): Define.
> * tree.c (cp_tree_equal): Handle SIZEOF_EXPR with
> SIZEOF_EXPR_TYPE_P.
...etc.
Looks like this caused a regression; PR54897, where the error
message seems to indicate an ABI change.
There's now an "excess error":
x/libstdc++-v3/testsuite/23_containers/bitset/45713.cc:24:55:
error: size of array 'test' is not an integral constant-expression
int test[sizeof(std::bitset<0xffffffff>) != 1 ? 1 : -1];
Or is the error message in error and just "missing" before?
Please have a look.
brgds, H-P
^ permalink raw reply [flat|nested] 10+ messages in thread
* Committed, PR54897 (was: [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2))
2012-10-11 0:41 ` Hans-Peter Nilsson
@ 2012-10-11 11:54 ` Hans-Peter Nilsson
0 siblings, 0 replies; 10+ messages in thread
From: Hans-Peter Nilsson @ 2012-10-11 11:54 UTC (permalink / raw)
To: gcc-patches, libstdc++
> From: Hans-Peter Nilsson <hp@axis.com>
> Date: Thu, 11 Oct 2012 02:13:32 +0200
> There's now an "excess error":
>
> x/libstdc++-v3/testsuite/23_containers/bitset/45713.cc:24:55:
> error: size of array 'test' is not an integral constant-expression
> int test[sizeof(std::bitset<0xffffffff>) != 1 ? 1 : -1];
>
> Or is the error message in error and just "missing" before?
> Please have a look.
As per discussion in PR54897, I committed the following, after
correcting the target syntax in the cutnpasted patch there.
(The target parser is picky about matching *-*-*, which I guess is
appropriate since it has to handle effective-targets as well.)
PR testsuite/54897
* testsuite/23_containers/bitset/45713.cc: Skip for avr*-*-*
cris*-*-* h8300*-*-* mcore*-*-* moxie*-*-*.
Index: libstdc++-v3/testsuite/23_containers/bitset/45713.cc
===================================================================
--- libstdc++-v3/testsuite/23_containers/bitset/45713.cc (revision 192353)
+++ libstdc++-v3/testsuite/23_containers/bitset/45713.cc (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2010 Free Software Foundation, Inc.
+// Copyright (C) 2010, 2012 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -15,7 +15,10 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-do compile }
+// The testcase requires bitsizetype to be wider than sizetype,
+// otherwise types/vars with 0x20000000 bytes or larger can't be used.
+// See http://gcc.gnu.org/PR54897
+// { dg-do compile { target { ! { avr*-*-* cris*-*-* h8300*-*-* mcore*-*-* moxie*-*-* } } } }
#include <bitset>
brgds, H-P
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2)
2012-10-02 12:57 ` [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2) Jakub Jelinek
` (2 preceding siblings ...)
2012-10-11 0:41 ` Hans-Peter Nilsson
@ 2012-10-26 13:36 ` Roman Zhuykov
3 siblings, 0 replies; 10+ messages in thread
From: Roman Zhuykov @ 2012-10-26 13:36 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Jason Merrill, gcc-patches
This caused
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55081
--
Roman Zhuykov
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2012-10-26 13:21 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-16 19:20 [C++ PATCH] -Wsizeof-pointer-memaccess warning Jakub Jelinek
2012-09-19 13:58 ` Jason Merrill
2012-09-25 16:28 ` Jakub Jelinek
2012-10-02 12:57 ` [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2) Jakub Jelinek
2012-10-03 9:14 ` Dodji Seketeli
2012-10-03 9:43 ` Jakub Jelinek
2012-10-05 13:45 ` Jason Merrill
2012-10-11 0:41 ` Hans-Peter Nilsson
2012-10-11 11:54 ` Committed, PR54897 (was: [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2)) Hans-Peter Nilsson
2012-10-26 13:36 ` [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2) Roman Zhuykov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).