From 0d23cf7a4f9609763b600a7e9edf81e78e3f7a55 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 5 Oct 2012 21:30:39 +0200 Subject: [PATCH] cp-tree.h (SIZEOF_EXPR_TYPE_P): Define. 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. From-SVN: r192141 --- gcc/cp/ChangeLog | 35 + gcc/cp/call.c | 2 +- gcc/cp/cp-gimplify.c | 19 +- gcc/cp/cp-tree.h | 5 + gcc/cp/cxx-pretty-print.c | 10 +- gcc/cp/decl.c | 102 ++- gcc/cp/error.c | 4 +- gcc/cp/mangle.c | 8 +- gcc/cp/parser.c | 29 +- gcc/cp/pt.c | 98 ++- gcc/cp/semantics.c | 45 +- gcc/cp/tree.c | 4 + gcc/cp/typeck.c | 9 +- gcc/testsuite/ChangeLog | 9 + gcc/testsuite/g++.dg/ext/builtin30.C | 27 + gcc/testsuite/g++.dg/ext/vla12.C | 28 + .../torture/Wsizeof-pointer-memaccess1.C | 702 +++++++++++++++++ .../torture/Wsizeof-pointer-memaccess2.C | 716 ++++++++++++++++++ .../g++.dg/warn/Wnull-conversion-1.C | 2 +- gcc/testsuite/g++.dg/warn/Wsign-compare-5.C | 20 + .../g++.dg/warn/Wsizeof-pointer-memaccess-1.C | 13 + gcc/testsuite/gcc.dg/builtins-85.c | 25 + libstdc++-v3/ChangeLog | 5 + .../20_util/shared_ptr/cons/43820_neg.cc | 4 +- 24 files changed, 1843 insertions(+), 78 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/builtin30.C create mode 100644 gcc/testsuite/g++.dg/ext/vla12.C create mode 100644 gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C create mode 100644 gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C create mode 100644 gcc/testsuite/g++.dg/warn/Wsign-compare-5.C create mode 100644 gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C create mode 100644 gcc/testsuite/gcc.dg/builtins-85.c diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index fe72a9ca7e4..458b76231ef 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,38 @@ +2012-10-05 Jakub Jelinek + + * 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. + 2012-10-04 Arnaud Charlet * decl2.c (cp_write_global_declarations): Fix handling of diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d0492d8deef..006cf41bc0e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -557,7 +557,7 @@ 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 = maybe_constant_value (t); STRIP_NOPS (t); if (integer_zerop (t) && !TREE_OVERFLOW (t)) return true; diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index dd2ef067c8f..6178993fe89 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -1,6 +1,7 @@ /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, + 2012 Free Software Foundation, Inc. Contributed by Jason Merrill @@ -1119,6 +1120,22 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) 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); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index bfe7ad70e0c..034668d8500 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -78,6 +78,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. @@ -4055,6 +4056,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #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. */ diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 03d9149f4cf..ce64a7b2377 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -1,6 +1,6 @@ /* Implementation of subroutines for the GNU C++ pretty-printer. Copyright (C) 2003, 2004, 2005, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis This file is part of GCC. @@ -798,7 +798,13 @@ pp_cxx_unary_expression (cxx_pretty_printer *pp, tree t) 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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d0933efc8dd..72754a92e99 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2160,39 +2160,40 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) 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. */ @@ -7931,6 +7932,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 @@ -8126,8 +8157,21 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) 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.) */ diff --git a/gcc/cp/error.c b/gcc/cp/error.c index c8b614b165c..e1aa938ddc8 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -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); diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 13c658b29e2..eee44a1bae2 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1,6 +1,6 @@ /* Name mangling for the 3.0 C++ ABI. Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + 2011, 2012 Free Software Foundation, Inc. Written by Alex Samuel This file is part of GCC. @@ -2580,6 +2580,12 @@ write_expression (tree expr) write_mangled_name (expr, false); 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))) { diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 155b51a180d..baaa8095602 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6383,17 +6383,19 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_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 *parser, bool address_p, bool cast_p, "ISO C++ does not allow % " "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: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 104d4dd6898..c3fb5e8feb2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12031,14 +12031,16 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) 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_flags_t complain, tree in_decl) 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 expression) } 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 *walk_subtrees, 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) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 68cbb4ba8c4..17ac36f67b9 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2170,8 +2170,25 @@ finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual, 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 constexpr_call *call, tree t, 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 @@ -8107,12 +8139,6 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) 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) @@ -8633,6 +8659,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) 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; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 7dddf2299c3..60dc54959bb 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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)) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 884f7d0573b..ce779075d3a 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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); } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ba310754789..28a4f57a6b5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,14 @@ 2012-10-05 Jakub Jelinek + * 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. + PR debug/54519 * gcc.dg/guality/pr54519-1.c: New test. * gcc.dg/guality/pr54519-2.c: New test. diff --git a/gcc/testsuite/g++.dg/ext/builtin30.C b/gcc/testsuite/g++.dg/ext/builtin30.C new file mode 100644 index 00000000000..d0a75fb173d --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/builtin30.C @@ -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" } } diff --git a/gcc/testsuite/g++.dg/ext/vla12.C b/gcc/testsuite/g++.dg/ext/vla12.C new file mode 100644 index 00000000000..bca836507a9 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/vla12.C @@ -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); +} diff --git a/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C b/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C new file mode 100644 index 00000000000..c57096cc063 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C @@ -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\]*" } diff --git a/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C b/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C new file mode 100644 index 00000000000..d5a29d8f582 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C @@ -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 +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 +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 +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 +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\]*" } diff --git a/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C b/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C index 511f091f2cf..84a1d380bb7 100644 --- a/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C +++ b/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C @@ -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" } } diff --git a/gcc/testsuite/g++.dg/warn/Wsign-compare-5.C b/gcc/testsuite/g++.dg/warn/Wsign-compare-5.C new file mode 100644 index 00000000000..641c49972ee --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wsign-compare-5.C @@ -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; +} diff --git a/gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C b/gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C new file mode 100644 index 00000000000..e2ba8769b9a --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C @@ -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]; +} diff --git a/gcc/testsuite/gcc.dg/builtins-85.c b/gcc/testsuite/gcc.dg/builtins-85.c new file mode 100644 index 00000000000..0993fbc19f4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-85.c @@ -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" } } */ diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 45c6e69172b..ed0b7077f26 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,8 @@ +2012-10-05 Jakub Jelinek + + * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust line + numbers. + 2012-10-05 Marc Glisse PR libstdc++/54686 diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc index dc9d80383f8..a2ceeb5c277 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc @@ -32,9 +32,9 @@ void test01() { X* px = 0; std::shared_ptr p1(px); // { dg-error "here" } - // { dg-error "incomplete" "" { target *-*-* } 776 } + // { dg-error "incomplete" "" { target *-*-* } 775 } std::shared_ptr p9(ap()); // { dg-error "here" } - // { dg-error "incomplete" "" { target *-*-* } 310 } + // { dg-error "incomplete" "" { target *-*-* } 307 } }