From patchwork Tue Oct 2 12:56:29 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 188499 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 688C82C00A2 for ; Tue, 2 Oct 2012 22:57:12 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1349787433; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Cc:Subject:Message-ID:Reply-To: References:MIME-Version:Content-Type:Content-Disposition: In-Reply-To:User-Agent:Mailing-List:Precedence:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=CEZykP/PpmrJSQpGj0xAEEe0p1c=; b=WHP+bwNJ7Py2O9J djsOyyWGHywfmYgYiBx/rkZsKRJh1l9ksCqepWQat8i1RQcdpV0gRIygGHj/Uv53 D9AKKQdzPY1/quYNt+c2DCW/sA7BjIUTGDGYeixV1MirMc7DswbxsJULqMMiL0kR YIQfa3JJ9RTQIw9SLw5lONyMiaVQ= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:Date:From:To:Cc:Subject:Message-ID:Reply-To:References:MIME-Version:Content-Type:Content-Disposition:In-Reply-To:User-Agent:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=mRnTeLGLgVH+UPuNqfWl4jehWOE6D66WwLkWPOcknQq1g4h2q0Yrc55n1wXltK +XUW0DRU+x8ggdSD0wywOIlrj2as8VqDA8l4+SZRRyvo04/MDr0hgo7gYW3oCzJV tuQV9j/RmVmHWUaTWWV/ntS87xrKH2oxGd2DiOVlCDwTg=; Received: (qmail 20252 invoked by alias); 2 Oct 2012 12:57:06 -0000 Received: (qmail 20233 invoked by uid 22791); 2 Oct 2012 12:56:54 -0000 X-SWARE-Spam-Status: No, hits=-7.2 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, KHOP_SPAMHAUS_DROP, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_CP, TW_CX X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 02 Oct 2012 12:56:33 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q92CuXWV016006 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 2 Oct 2012 08:56:33 -0400 Received: from zalov.redhat.com (vpn1-4-137.ams2.redhat.com [10.36.4.137]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q92CuUlf031171 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 2 Oct 2012 08:56:32 -0400 Received: from zalov.cz (localhost [127.0.0.1]) by zalov.redhat.com (8.14.5/8.14.5) with ESMTP id q92CuUjD030307; Tue, 2 Oct 2012 14:56:30 +0200 Received: (from jakub@localhost) by zalov.cz (8.14.5/8.14.5/Submit) id q92CuTNY030306; Tue, 2 Oct 2012 14:56:29 +0200 Date: Tue, 2 Oct 2012 14:56:29 +0200 From: Jakub Jelinek To: Jason Merrill Cc: gcc-patches@gcc.gnu.org Subject: [C++ PATCH] -Wsizeof-pointer-memaccess warning (take 2) Message-ID: <20121002125629.GJ1787@tucnak.redhat.com> Reply-To: Jakub Jelinek References: <20120816191535.GM1999@tucnak.redhat.com> <5059CF5F.4030308@redhat.com> <20120925153640.GM1787@tucnak.redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20120925153640.GM1787@tucnak.redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org On Tue, Sep 25, 2012 at 05:36:40PM +0200, Jakub Jelinek wrote: > Here is the current patch. One issue already mentioned on IRC is > that generic code like contains_placeholder_p, save_expr etc. > got confused by SIZEOF_EXPR having type as argument instead of expression. > So for !processing_template_decl this patch uses instead NOP_EXPR with > error_mark_node operand and type on the NOP_EXPR, plus SIZEOF_EXPR_TYPE_P > bit set on the SIZEOF_EXPR (we need location on the sizeof expression, so > it should be expression). The patch solves that thing. > > The remaining unsolved issues are two regressions, one is error > FAIL: g++.dg/warn/Wnull-conversion-1.C -std=gnu++98 (test for excess errors) > FAIL: g++.dg/warn/Wnull-conversion-1.C -std=gnu++11 (test for excess errors) > on the > int* r = sizeof(char) / 2; > line. Is that even valid C++11? C++03? The thing is that we previously > immediately folded sizeof(char) to 1, and 1/2 into 0 and considered that as > null_ptr_cst_p. With the patch we don't fold it anymore right away, we This patch uses maybe_constant_value for C++98/03, and makes the above an error for C++11 (where the standard says that only literal 0 is null pointer constant?). > The other issue is Obj-C++ ICE, in cp_build_binary_op I've added ... > No idea what to do about that unfortunately, we don't have any handy macro > to tell us the ObjC tree code range, we'd need to enumerate the Obj-C++ tree > codes which we don't want to ICE on (and just set *non_constant_p on them > instead). We have objc_is_property_ref predicate, but not sure about the > other ObjC trees. And this is solved by saying objc_is_property_ref is not a potential_constant_expression and removing the early return for C++98/03. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2012-10-02 Jakub Jelinek 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. Jakub --- gcc/cp/cp-tree.h.jj 2012-10-01 10:08:40.447237104 +0200 +++ gcc/cp/cp-tree.h 2012-10-01 17:38:18.506576783 +0200 @@ -79,6 +79,7 @@ c-common.h, not after. OVL_ARG_DEPENDENT (in OVERLOAD) PACK_EXPANSION_LOCAL_P (in *_PACK_EXPANSION) TINFO_RECHECK_ACCESS_P (in TEMPLATE_INFO) + SIZEOF_EXPR_TYPE_P (in SIZEOF_EXPR) 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -4044,6 +4045,10 @@ more_aggr_init_expr_args_p (const aggr_i #define CONVERT_EXPR_VBASE_PATH(NODE) \ TREE_LANG_FLAG_0 (CONVERT_EXPR_CHECK (NODE)) +/* True if SIZEOF_EXPR argument is type. */ +#define SIZEOF_EXPR_TYPE_P(NODE) \ + TREE_LANG_FLAG_0 (SIZEOF_EXPR_CHECK (NODE)) + /* An enumeration of the kind of tags that C++ accepts. */ enum tag_types { none_type = 0, /* Not a tag type. */ --- gcc/cp/cp-gimplify.c.jj 2012-09-27 12:45:49.060392494 +0200 +++ gcc/cp/cp-gimplify.c 2012-10-01 17:38:18.507576775 +0200 @@ -1119,6 +1119,22 @@ cp_genericize_r (tree *stmt_p, int *walk genericize_break_stmt (stmt_p); else if (TREE_CODE (stmt) == OMP_FOR) genericize_omp_for_stmt (stmt_p, walk_subtrees, data); + else if (TREE_CODE (stmt) == SIZEOF_EXPR) + { + if (SIZEOF_EXPR_TYPE_P (stmt)) + *stmt_p + = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (stmt, 0)), + SIZEOF_EXPR, false); + else if (TYPE_P (TREE_OPERAND (stmt, 0))) + *stmt_p = cxx_sizeof_or_alignof_type (TREE_OPERAND (stmt, 0), + SIZEOF_EXPR, false); + else + *stmt_p = cxx_sizeof_or_alignof_expr (TREE_OPERAND (stmt, 0), + SIZEOF_EXPR, false); + if (*stmt_p == error_mark_node) + *stmt_p = size_one_node; + return NULL; + } pointer_set_insert (p_set, *stmt_p); --- gcc/cp/call.c.jj 2012-09-27 12:45:49.000000000 +0200 +++ gcc/cp/call.c 2012-10-01 17:53:17.594609236 +0200 @@ -557,7 +557,10 @@ null_ptr_cst_p (tree t) { /* Core issue 903 says only literal 0 is a null pointer constant. */ if (cxx_dialect < cxx0x) - t = integral_constant_value (t); + { + t = integral_constant_value (t); + t = maybe_constant_value (t); + } STRIP_NOPS (t); if (integer_zerop (t) && !TREE_OVERFLOW (t)) return true; --- gcc/cp/semantics.c.jj 2012-09-27 12:45:49.296391214 +0200 +++ gcc/cp/semantics.c 2012-10-01 17:50:27.088550744 +0200 @@ -2170,8 +2170,25 @@ finish_call_expr (tree fn, VEC(tree,gc) result = resolve_overloaded_builtin (input_location, fn, *args); if (!result) - /* A call to a namespace-scope function. */ - result = build_new_function_call (fn, args, koenig_p, complain); + { + if (warn_sizeof_pointer_memaccess + && !VEC_empty(tree, *args) + && TREE_CODE (VEC_last(tree, *args)) == SIZEOF_EXPR + && !processing_template_decl) + { + tree sizeof_arg = VEC_last(tree, *args); + if (SIZEOF_EXPR_TYPE_P (sizeof_arg)) + sizeof_arg = TREE_TYPE (TREE_OPERAND (sizeof_arg, 0)); + else + sizeof_arg = TREE_OPERAND (sizeof_arg, 0); + sizeof_pointer_memaccess_warning + (EXPR_LOCATION (VEC_last(tree, *args)), fn, *args, + sizeof_arg, same_type_ignoring_top_level_qualifiers_p); + } + + /* A call to a namespace-scope function. */ + result = build_new_function_call (fn, args, koenig_p, complain); + } } else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR) { @@ -7723,6 +7740,21 @@ cxx_eval_constant_expression (const cons non_constant_p); break; + case SIZEOF_EXPR: + if (SIZEOF_EXPR_TYPE_P (t)) + r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)), + SIZEOF_EXPR, false); + else if (TYPE_P (TREE_OPERAND (t, 0))) + r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR, + false); + else + r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR, + false); + if (r == error_mark_node) + r = size_one_node; + VERIFY_CONSTANT (r); + break; + case COMPOUND_EXPR: { /* check_return_expr sometimes wraps a TARGET_EXPR in a @@ -8106,12 +8138,6 @@ potential_constant_expression_1 (tree t, int i; tree tmp; - /* C++98 has different rules for the form of a constant expression that - are enforced in the parser, so we can assume that anything that gets - this far is suitable. */ - if (cxx_dialect < cxx0x) - return true; - if (t == error_mark_node) return false; if (t == NULL_TREE) @@ -8632,6 +8658,9 @@ potential_constant_expression_1 (tree t, return false; default: + if (objc_is_property_ref (t)) + return false; + sorry ("unexpected AST of kind %s", tree_code_name[TREE_CODE (t)]); gcc_unreachable(); return false; --- gcc/cp/tree.c.jj 2012-09-27 12:45:49.083392369 +0200 +++ gcc/cp/tree.c 2012-10-01 17:38:18.512576744 +0200 @@ -2602,6 +2602,10 @@ cp_tree_equal (tree t1, tree t2) tree o1 = TREE_OPERAND (t1, 0); tree o2 = TREE_OPERAND (t2, 0); + if (SIZEOF_EXPR_TYPE_P (t1)) + o1 = TREE_TYPE (o1); + if (SIZEOF_EXPR_TYPE_P (t2)) + o2 = TREE_TYPE (o2); if (TREE_CODE (o1) != TREE_CODE (o2)) return false; if (TYPE_P (o1)) --- gcc/cp/mangle.c.jj 2012-09-27 12:45:49.111392217 +0200 +++ gcc/cp/mangle.c 2012-10-01 17:38:18.513576740 +0200 @@ -2581,6 +2581,12 @@ write_expression (tree expr) write_char ('E'); } else if (TREE_CODE (expr) == SIZEOF_EXPR + && SIZEOF_EXPR_TYPE_P (expr)) + { + write_string ("st"); + write_type (TREE_TYPE (TREE_OPERAND (expr, 0))); + } + else if (TREE_CODE (expr) == SIZEOF_EXPR && TYPE_P (TREE_OPERAND (expr, 0))) { write_string ("st"); --- gcc/cp/decl.c.jj 2012-10-01 10:08:40.429237206 +0200 +++ gcc/cp/decl.c 2012-10-01 17:38:18.516576724 +0200 @@ -2160,39 +2160,40 @@ duplicate_decls (tree newdecl, tree oldd DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl); DECL_RESULT (olddecl) = DECL_RESULT (newdecl); } + /* If redeclaring a builtin function, it stays built in + if newdecl is a gnu_inline definition, or if newdecl is just + a declaration. */ + if (DECL_BUILT_IN (olddecl) + && (new_defines_function ? GNU_INLINE_P (newdecl) : types_match)) + { + DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); + DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); + /* If we're keeping the built-in definition, keep the rtl, + regardless of declaration matches. */ + COPY_DECL_RTL (olddecl, newdecl); + if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL) + { + enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl); + switch (fncode) + { + /* If a compatible prototype of these builtin functions + is seen, assume the runtime implements it with the + expected semantics. */ + case BUILT_IN_STPCPY: + if (builtin_decl_explicit_p (fncode)) + set_builtin_decl_implicit_p (fncode, true); + break; + default: + break; + } + } + } if (new_defines_function) /* If defining a function declared with other language linkage, use the previously declared language linkage. */ SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl)); else if (types_match) { - /* If redeclaring a builtin function, and not a definition, - it stays built in. */ - if (DECL_BUILT_IN (olddecl)) - { - DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); - DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); - /* If we're keeping the built-in definition, keep the rtl, - regardless of declaration matches. */ - COPY_DECL_RTL (olddecl, newdecl); - if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL) - { - enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl); - switch (fncode) - { - /* If a compatible prototype of these builtin functions - is seen, assume the runtime implements it with the - expected semantics. */ - case BUILT_IN_STPCPY: - if (builtin_decl_explicit_p (fncode)) - set_builtin_decl_implicit_p (fncode, true); - break; - default: - break; - } - } - } - DECL_RESULT (newdecl) = DECL_RESULT (olddecl); /* Don't clear out the arguments if we're just redeclaring a function. */ @@ -7928,6 +7929,36 @@ stabilize_vla_size (tree size) struct pointer_set_t *pset = pointer_set_create (); /* Break out any function calls into temporary variables. */ cp_walk_tree (&size, stabilize_save_expr_r, pset, pset); + pointer_set_destroy (pset); +} + +/* Helper function for compute_array_index_type. Look for SIZEOF_EXPR + not inside of SAVE_EXPR and fold them. */ + +static tree +fold_sizeof_expr_r (tree *expr_p, int *walk_subtrees, void *data) +{ + tree expr = *expr_p; + if (TREE_CODE (expr) == SAVE_EXPR || TYPE_P (expr)) + *walk_subtrees = 0; + else if (TREE_CODE (expr) == SIZEOF_EXPR) + { + *(bool *)data = true; + if (SIZEOF_EXPR_TYPE_P (expr)) + expr = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (expr, 0)), + SIZEOF_EXPR, false); + else if (TYPE_P (TREE_OPERAND (expr, 0))) + expr = cxx_sizeof_or_alignof_type (TREE_OPERAND (expr, 0), SIZEOF_EXPR, + false); + else + expr = cxx_sizeof_or_alignof_expr (TREE_OPERAND (expr, 0), SIZEOF_EXPR, + false); + if (expr == error_mark_node) + expr = size_one_node; + *expr_p = expr; + *walk_subtrees = 0; + } + return NULL; } /* Given the SIZE (i.e., number of elements) in an array, compute an @@ -8123,8 +8154,21 @@ compute_array_index_type (tree name, tre processing_template_decl = saved_processing_template_decl; if (!TREE_CONSTANT (itype)) - /* A variable sized array. */ - itype = variable_size (itype); + { + /* A variable sized array. */ + itype = variable_size (itype); + if (TREE_CODE (itype) != SAVE_EXPR) + { + /* Look for SIZEOF_EXPRs in itype and fold them, otherwise + they might survive till gimplification. */ + tree newitype = itype; + bool found = false; + cp_walk_tree_without_duplicates (&newitype, + fold_sizeof_expr_r, &found); + if (found) + itype = variable_size (fold (newitype)); + } + } /* Make sure that there was no overflow when creating to a signed index type. (For example, on a 32-bit machine, an array with size 2^32 - 1 is too big.) */ --- gcc/cp/cxx-pretty-print.c.jj 2012-09-27 12:45:49.118392179 +0200 +++ gcc/cp/cxx-pretty-print.c 2012-10-01 17:38:18.518576711 +0200 @@ -798,7 +798,13 @@ pp_cxx_unary_expression (cxx_pretty_prin case ALIGNOF_EXPR: pp_cxx_ws_string (pp, code == SIZEOF_EXPR ? "sizeof" : "__alignof__"); pp_cxx_whitespace (pp); - if (TYPE_P (TREE_OPERAND (t, 0))) + if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t)) + { + pp_cxx_left_paren (pp); + pp_cxx_type_id (pp, TREE_TYPE (TREE_OPERAND (t, 0))); + pp_cxx_right_paren (pp); + } + else if (TYPE_P (TREE_OPERAND (t, 0))) { pp_cxx_left_paren (pp); pp_cxx_type_id (pp, TREE_OPERAND (t, 0)); --- gcc/cp/typeck.c.jj 2012-09-27 12:45:49.208391691 +0200 +++ gcc/cp/typeck.c 2012-10-01 17:38:18.519576704 +0200 @@ -4624,7 +4624,14 @@ cp_build_binary_op (location_t location, && !enum_cast_to_int (orig_op0) && !enum_cast_to_int (orig_op1)) { - warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1, + tree oop0 = maybe_constant_value (orig_op0); + tree oop1 = maybe_constant_value (orig_op1); + + if (TREE_CODE (oop0) != INTEGER_CST) + oop0 = orig_op0; + if (TREE_CODE (oop1) != INTEGER_CST) + oop1 = orig_op1; + warn_for_sign_compare (location, oop0, oop1, op0, op1, result_type, resultcode); } } --- gcc/cp/parser.c.jj 2012-10-01 10:08:40.447237104 +0200 +++ gcc/cp/parser.c 2012-10-01 17:38:18.524576680 +0200 @@ -6383,17 +6383,19 @@ cp_parser_unary_expression (cp_parser *p case RID_ALIGNOF: case RID_SIZEOF: { - tree operand; + tree operand, ret; enum tree_code op; + location_t first_loc; op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); + first_loc = cp_lexer_peek_token (parser->lexer)->location; /* Parse the operand. */ operand = cp_parser_sizeof_operand (parser, keyword); if (TYPE_P (operand)) - return cxx_sizeof_or_alignof_type (operand, op, true); + ret = cxx_sizeof_or_alignof_type (operand, op, true); else { /* ISO C++ defines alignof only with types, not with @@ -6404,8 +6406,29 @@ cp_parser_unary_expression (cp_parser *p "ISO C++ does not allow % " "with a non-type"); - return cxx_sizeof_or_alignof_expr (operand, op, true); + ret = cxx_sizeof_or_alignof_expr (operand, op, true); } + /* For SIZEOF_EXPR, just issue diagnostics, but keep + SIZEOF_EXPR with the original operand. */ + if (op == SIZEOF_EXPR && ret != error_mark_node) + { + if (TREE_CODE (ret) != SIZEOF_EXPR || TYPE_P (operand)) + { + if (!processing_template_decl && TYPE_P (operand)) + { + ret = build_min (SIZEOF_EXPR, size_type_node, + build1 (NOP_EXPR, operand, + error_mark_node)); + SIZEOF_EXPR_TYPE_P (ret) = 1; + } + else + ret = build_min (SIZEOF_EXPR, size_type_node, operand); + TREE_SIDE_EFFECTS (ret) = 0; + TREE_READONLY (ret) = 1; + } + SET_EXPR_LOCATION (ret, first_loc); + } + return ret; } case RID_NEW: --- gcc/cp/pt.c.jj 2012-10-01 10:08:40.445237116 +0200 +++ gcc/cp/pt.c 2012-10-01 17:38:18.529576651 +0200 @@ -12031,14 +12031,16 @@ tsubst_copy (tree t, tree args, tsubst_f if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))) { - tree expanded; + tree expanded, op = TREE_OPERAND (t, 0); int len = 0; + if (SIZEOF_EXPR_TYPE_P (t)) + op = TREE_TYPE (op); + ++cp_unevaluated_operand; ++c_inhibit_evaluation_warnings; /* We only want to compute the number of arguments. */ - expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args, - complain, in_decl); + expanded = tsubst_pack_expansion (op, args, complain, in_decl); --cp_unevaluated_operand; --c_inhibit_evaluation_warnings; @@ -12065,6 +12067,16 @@ tsubst_copy (tree t, tree args, tsubst_f else return build_int_cst (size_type_node, len); } + if (SIZEOF_EXPR_TYPE_P (t)) + { + r = tsubst_copy (TREE_TYPE (TREE_OPERAND (t, 0)), + args, complain, in_decl); + r = build1 (NOP_EXPR, r, error_mark_node); + r = build1 (SIZEOF_EXPR, + tsubst (TREE_TYPE (t), args, complain, in_decl), r); + SIZEOF_EXPR_TYPE_P (r) = 1; + return r; + } /* Fall through */ case INDIRECT_REF: @@ -13468,31 +13480,56 @@ tsubst_copy_and_build (tree t, /* Fall through */ case ALIGNOF_EXPR: - op1 = TREE_OPERAND (t, 0); - if (!args) - { - /* When there are no ARGS, we are trying to evaluate a - non-dependent expression from the parser. Trying to do - the substitutions may not work. */ - if (!TYPE_P (op1)) - op1 = TREE_TYPE (op1); - } - else - { - ++cp_unevaluated_operand; - ++c_inhibit_evaluation_warnings; - op1 = tsubst_copy_and_build (op1, args, complain, in_decl, - /*function_p=*/false, - /*integral_constant_expression_p=*/false); - --cp_unevaluated_operand; - --c_inhibit_evaluation_warnings; - } - if (TYPE_P (op1)) - RETURN (cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), - complain & tf_error)); - else - RETURN (cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t), - complain & tf_error)); + { + tree r; + + op1 = TREE_OPERAND (t, 0); + if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t)) + op1 = TREE_TYPE (op1); + if (!args) + { + /* When there are no ARGS, we are trying to evaluate a + non-dependent expression from the parser. Trying to do + the substitutions may not work. */ + if (!TYPE_P (op1)) + op1 = TREE_TYPE (op1); + } + else + { + ++cp_unevaluated_operand; + ++c_inhibit_evaluation_warnings; + op1 = tsubst_copy_and_build (op1, args, complain, in_decl, + /*function_p=*/false, + /*integral_constant_expression_p=*/ + false); + --cp_unevaluated_operand; + --c_inhibit_evaluation_warnings; + } + if (TYPE_P (op1)) + r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), + complain & tf_error); + else + r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t), + complain & tf_error); + if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node) + { + if (TREE_CODE (r) != SIZEOF_EXPR || TYPE_P (op1)) + { + if (TYPE_P (op1)) + { + r = build_min (SIZEOF_EXPR, size_type_node, + build1 (NOP_EXPR, op1, error_mark_node)); + SIZEOF_EXPR_TYPE_P (r) = 1; + } + else + r = build_min (SIZEOF_EXPR, size_type_node, op1); + TREE_SIDE_EFFECTS (r) = 0; + TREE_READONLY (r) = 1; + } + SET_EXPR_LOCATION (r, EXPR_LOCATION (t)); + } + RETURN (r); + } case AT_ENCODE_EXPR: { @@ -19288,6 +19325,9 @@ value_dependent_expression_p (tree expre } case SIZEOF_EXPR: + if (SIZEOF_EXPR_TYPE_P (expression)) + return dependent_type_p (TREE_TYPE (TREE_OPERAND (expression, 0))); + /* FALLTHRU */ case ALIGNOF_EXPR: case TYPEID_EXPR: /* A `sizeof' expression is value-dependent if the operand is @@ -19627,6 +19667,8 @@ instantiation_dependent_r (tree *tp, int case TRAIT_EXPR: { tree op = TREE_OPERAND (*tp, 0); + if (code == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (*tp)) + op = TREE_TYPE (op); if (TYPE_P (op)) { if (dependent_type_p (op) --- gcc/cp/error.c.jj 2012-09-27 12:45:49.151391999 +0200 +++ gcc/cp/error.c 2012-10-01 17:38:18.532576635 +0200 @@ -2312,7 +2312,9 @@ dump_expr (tree t, int flags) } pp_cxx_whitespace (cxx_pp); pp_cxx_left_paren (cxx_pp); - if (TYPE_P (TREE_OPERAND (t, 0))) + if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t)) + dump_type (TREE_TYPE (TREE_OPERAND (t, 0)), flags); + else if (TYPE_P (TREE_OPERAND (t, 0))) dump_type (TREE_OPERAND (t, 0), flags); else dump_expr (TREE_OPERAND (t, 0), flags); --- gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C.jj 2012-10-01 17:38:18.549576540 +0200 +++ gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C 2012-10-01 17:38:18.549576540 +0200 @@ -0,0 +1,716 @@ +// Test -Wsizeof-pointer-memaccess warnings. +// { dg-do compile } +// { dg-options "-Wall" } +// Test just twice, once with -O0 non-fortified, once with -O2 fortified. +// { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } } +// { dg-skip-if "" { *-*-* } { "-flto" } { "" } } + +extern "C" { + +typedef __SIZE_TYPE__ size_t; +extern void *memset (void *, int, size_t); +extern void *memcpy (void *__restrict, const void *__restrict, size_t); +extern void *memmove (void *__restrict, const void *__restrict, size_t); +extern int memcmp (const void *, const void *, size_t); +extern char *strncpy (char *__restrict, const char *__restrict, size_t); +extern char *strncat (char *__restrict, const char *__restrict, size_t); +extern char *strndup (const char *, size_t); +extern int strncmp (const char *, const char *, size_t); +extern int strncasecmp (const char *, const char *, size_t); + +#ifdef __OPTIMIZE__ +# define bos(ptr) __builtin_object_size (ptr, 1) +# define bos0(ptr) __builtin_object_size (ptr, 0) + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memset (void *dest, int c, size_t len) +{ + return __builtin___memset_chk (dest, c, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memcpy (void *__restrict dest, const void *__restrict src, size_t len) +{ + return __builtin___memcpy_chk (dest, src, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memmove (void *dest, const void *src, size_t len) +{ + return __builtin___memmove_chk (dest, src, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline char * +strncpy (char *__restrict dest, const char *__restrict src, size_t len) +{ + return __builtin___strncpy_chk (dest, src, len, bos (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline char * +strncat (char *dest, const char *src, size_t len) +{ + return __builtin___strncat_chk (dest, src, len, bos (dest)); +} +#endif + +} + +struct A { short a, b; int c, d; long e, f; }; +typedef struct A TA; +typedef struct A *PA; +typedef TA *PTA; +struct B {}; +typedef struct B TB; +typedef struct B *PB; +typedef TB *PTB; +typedef int X[3][3][3]; + +template +int +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\]*" } --- gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C.jj 2012-10-01 17:38:18.549576540 +0200 +++ gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C 2012-10-01 17:38:18.549576540 +0200 @@ -0,0 +1,702 @@ +// Test -Wsizeof-pointer-memaccess warnings. +// { dg-do compile } +// { dg-options "-Wall" } +// Test just twice, once with -O0 non-fortified, once with -O2 fortified. +// { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } } +// { dg-skip-if "" { *-*-* } { "-flto" } { "" } } + +extern "C" { + +typedef __SIZE_TYPE__ size_t; +extern void *memset (void *, int, size_t); +extern void *memcpy (void *__restrict, const void *__restrict, size_t); +extern void *memmove (void *__restrict, const void *__restrict, size_t); +extern int memcmp (const void *, const void *, size_t); +extern char *strncpy (char *__restrict, const char *__restrict, size_t); +extern char *strncat (char *__restrict, const char *__restrict, size_t); +extern char *strndup (const char *, size_t); +extern int strncmp (const char *, const char *, size_t); +extern int strncasecmp (const char *, const char *, size_t); + +#ifdef __OPTIMIZE__ +# define bos(ptr) __builtin_object_size (ptr, 1) +# define bos0(ptr) __builtin_object_size (ptr, 0) + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memset (void *dest, int c, size_t len) +{ + return __builtin___memset_chk (dest, c, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memcpy (void *__restrict dest, const void *__restrict src, size_t len) +{ + return __builtin___memcpy_chk (dest, src, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memmove (void *dest, const void *src, size_t len) +{ + return __builtin___memmove_chk (dest, src, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline char * +strncpy (char *__restrict dest, const char *__restrict src, size_t len) +{ + return __builtin___strncpy_chk (dest, src, len, bos (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline char * +strncat (char *dest, const char *src, size_t len) +{ + return __builtin___strncat_chk (dest, src, len, bos (dest)); +} +#endif + +} + +struct A { short a, b; int c, d; long e, f; }; +typedef struct A TA; +typedef struct A *PA; +typedef TA *PTA; +struct B {}; +typedef struct B TB; +typedef struct B *PB; +typedef TB *PTB; +typedef int X[3][3][3]; + +int +f1 (void *x, int z) +{ + struct A a, *pa1 = &a; + TA *pa2 = &a; + PA pa3 = &a; + PTA pa4 = &a; + memset (&a, 0, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memset (pa1, 0, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa2, 0, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa3, 0, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa4, 0, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa1, 0, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pa2, 0, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pa3, 0, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pa4, 0, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memcpy (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa1, x, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pa4, x, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memcpy (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa1, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pa4, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + memmove (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memmove (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa1, x, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pa4, x, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memmove (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memmove (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa1, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pa4, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + z += memcmp (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa1, x, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + z += memcmp (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa1, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + // These are correct, no warning. + memset (&a, 0, sizeof a); + memset (&a, 0, sizeof (a)); + memset (&a, 0, sizeof (struct A)); + memset (&a, 0, sizeof (const struct A)); + memset (&a, 0, sizeof (volatile struct A)); + memset (&a, 0, sizeof (volatile const struct A)); + memset (&a, 0, sizeof (TA)); + memset (&a, 0, sizeof (__typeof (*&a))); + memset (pa1, 0, sizeof (*pa1)); + memset (pa2, 0, sizeof (*pa3)); + memset (pa3, 0, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memset ((void *) &a, 0, sizeof (&a)); + memset ((char *) &a, 0, sizeof (&a)); + memset (&a, 0, sizeof (&a) + 0); + memset (&a, 0, 0 + sizeof (&a)); + + // These are correct, no warning. + memcpy (&a, x, sizeof a); + memcpy (&a, x, sizeof (a)); + memcpy (&a, x, sizeof (struct A)); + memcpy (&a, x, sizeof (const struct A)); + memcpy (&a, x, sizeof (volatile struct A)); + memcpy (&a, x, sizeof (volatile const struct A)); + memcpy (&a, x, sizeof (TA)); + memcpy (&a, x, sizeof (__typeof (*&a))); + memcpy (pa1, x, sizeof (*pa1)); + memcpy (pa2, x, sizeof (*pa3)); + memcpy (pa3, x, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memcpy ((void *) &a, x, sizeof (&a)); + memcpy ((char *) &a, x, sizeof (&a)); + memcpy (&a, x, sizeof (&a) + 0); + memcpy (&a, x, 0 + sizeof (&a)); + + // These are correct, no warning. + memcpy (x, &a, sizeof a); + memcpy (x, &a, sizeof (a)); + memcpy (x, &a, sizeof (struct A)); + memcpy (x, &a, sizeof (const struct A)); + memcpy (x, &a, sizeof (volatile struct A)); + memcpy (x, &a, sizeof (volatile const struct A)); + memcpy (x, &a, sizeof (TA)); + memcpy (x, &a, sizeof (__typeof (*&a))); + memcpy (x, pa1, sizeof (*pa1)); + memcpy (x, pa2, sizeof (*pa3)); + memcpy (x, pa3, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memcpy (x, (void *) &a, sizeof (&a)); + memcpy (x, (char *) &a, sizeof (&a)); + memcpy (x, &a, sizeof (&a) + 0); + memcpy (x, &a, 0 + sizeof (&a)); + + // These are correct, no warning. + memmove (&a, x, sizeof a); + memmove (&a, x, sizeof (a)); + memmove (&a, x, sizeof (struct A)); + memmove (&a, x, sizeof (const struct A)); + memmove (&a, x, sizeof (volatile struct A)); + memmove (&a, x, sizeof (volatile const struct A)); + memmove (&a, x, sizeof (TA)); + memmove (&a, x, sizeof (__typeof (*&a))); + memmove (pa1, x, sizeof (*pa1)); + memmove (pa2, x, sizeof (*pa3)); + memmove (pa3, x, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memmove ((void *) &a, x, sizeof (&a)); + memmove ((char *) &a, x, sizeof (&a)); + memmove (&a, x, sizeof (&a) + 0); + memmove (&a, x, 0 + sizeof (&a)); + + // These are correct, no warning. + memmove (x, &a, sizeof a); + memmove (x, &a, sizeof (a)); + memmove (x, &a, sizeof (struct A)); + memmove (x, &a, sizeof (const struct A)); + memmove (x, &a, sizeof (volatile struct A)); + memmove (x, &a, sizeof (volatile const struct A)); + memmove (x, &a, sizeof (TA)); + memmove (x, &a, sizeof (__typeof (*&a))); + memmove (x, pa1, sizeof (*pa1)); + memmove (x, pa2, sizeof (*pa3)); + memmove (x, pa3, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memmove (x, (void *) &a, sizeof (&a)); + memmove (x, (char *) &a, sizeof (&a)); + memmove (x, &a, sizeof (&a) + 0); + memmove (x, &a, 0 + sizeof (&a)); + + // These are correct, no warning. + z += memcmp (&a, x, sizeof a); + z += memcmp (&a, x, sizeof (a)); + z += memcmp (&a, x, sizeof (struct A)); + z += memcmp (&a, x, sizeof (const struct A)); + z += memcmp (&a, x, sizeof (volatile struct A)); + z += memcmp (&a, x, sizeof (volatile const struct A)); + z += memcmp (&a, x, sizeof (TA)); + z += memcmp (&a, x, sizeof (__typeof (*&a))); + z += memcmp (pa1, x, sizeof (*pa1)); + z += memcmp (pa2, x, sizeof (*pa3)); + z += memcmp (pa3, x, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp ((void *) &a, x, sizeof (&a)); + z += memcmp ((char *) &a, x, sizeof (&a)); + z += memcmp (&a, x, sizeof (&a) + 0); + z += memcmp (&a, x, 0 + sizeof (&a)); + + // These are correct, no warning. + z += memcmp (x, &a, sizeof a); + z += memcmp (x, &a, sizeof (a)); + z += memcmp (x, &a, sizeof (struct A)); + z += memcmp (x, &a, sizeof (const struct A)); + z += memcmp (x, &a, sizeof (volatile struct A)); + z += memcmp (x, &a, sizeof (volatile const struct A)); + z += memcmp (x, &a, sizeof (TA)); + z += memcmp (x, &a, sizeof (__typeof (*&a))); + z += memcmp (x, pa1, sizeof (*pa1)); + z += memcmp (x, pa2, sizeof (*pa3)); + z += memcmp (x, pa3, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp (x, (void *) &a, sizeof (&a)); + z += memcmp (x, (char *) &a, sizeof (&a)); + z += memcmp (x, &a, sizeof (&a) + 0); + z += memcmp (x, &a, 0 + sizeof (&a)); + + return z; +} + +int +f2 (void *x, int z) +{ + struct B b, *pb1 = &b; + TB *pb2 = &b; + PB pb3 = &b; + PTB pb4 = &b; + memset (&b, 0, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memset (pb1, 0, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb2, 0, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb3, 0, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb4, 0, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb1, 0, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pb2, 0, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pb3, 0, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pb4, 0, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memcpy (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb1, x, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pb4, x, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memcpy (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb1, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pb4, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + memmove (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memmove (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb1, x, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pb4, x, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memmove (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memmove (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb1, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pb4, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + z += memcmp (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb1, x, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + z += memcmp (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb1, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + // These are correct, no warning. + memset (&b, 0, sizeof b); + memset (&b, 0, sizeof (b)); + memset (&b, 0, sizeof (struct B)); + memset (&b, 0, sizeof (const struct B)); + memset (&b, 0, sizeof (volatile struct B)); + memset (&b, 0, sizeof (volatile const struct B)); + memset (&b, 0, sizeof (TB)); + memset (&b, 0, sizeof (__typeof (*&b))); + memset (pb1, 0, sizeof (*pb1)); + memset (pb2, 0, sizeof (*pb3)); + memset (pb3, 0, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memset ((void *) &b, 0, sizeof (&b)); + memset ((char *) &b, 0, sizeof (&b)); + memset (&b, 0, sizeof (&b) + 0); + memset (&b, 0, 0 + sizeof (&b)); + + // These are correct, no warning. + memcpy (&b, x, sizeof b); + memcpy (&b, x, sizeof (b)); + memcpy (&b, x, sizeof (struct B)); + memcpy (&b, x, sizeof (const struct B)); + memcpy (&b, x, sizeof (volatile struct B)); + memcpy (&b, x, sizeof (volatile const struct B)); + memcpy (&b, x, sizeof (TB)); + memcpy (&b, x, sizeof (__typeof (*&b))); + memcpy (pb1, x, sizeof (*pb1)); + memcpy (pb2, x, sizeof (*pb3)); + memcpy (pb3, x, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memcpy ((void *) &b, x, sizeof (&b)); + memcpy ((char *) &b, x, sizeof (&b)); + memcpy (&b, x, sizeof (&b) + 0); + memcpy (&b, x, 0 + sizeof (&b)); + + // These are correct, no warning. + memcpy (x, &b, sizeof b); + memcpy (x, &b, sizeof (b)); + memcpy (x, &b, sizeof (struct B)); + memcpy (x, &b, sizeof (const struct B)); + memcpy (x, &b, sizeof (volatile struct B)); + memcpy (x, &b, sizeof (volatile const struct B)); + memcpy (x, &b, sizeof (TB)); + memcpy (x, &b, sizeof (__typeof (*&b))); + memcpy (x, pb1, sizeof (*pb1)); + memcpy (x, pb2, sizeof (*pb3)); + memcpy (x, pb3, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memcpy (x, (void *) &b, sizeof (&b)); + memcpy (x, (char *) &b, sizeof (&b)); + memcpy (x, &b, sizeof (&b) + 0); + memcpy (x, &b, 0 + sizeof (&b)); + + // These are correct, no warning. + memmove (&b, x, sizeof b); + memmove (&b, x, sizeof (b)); + memmove (&b, x, sizeof (struct B)); + memmove (&b, x, sizeof (const struct B)); + memmove (&b, x, sizeof (volatile struct B)); + memmove (&b, x, sizeof (volatile const struct B)); + memmove (&b, x, sizeof (TB)); + memmove (&b, x, sizeof (__typeof (*&b))); + memmove (pb1, x, sizeof (*pb1)); + memmove (pb2, x, sizeof (*pb3)); + memmove (pb3, x, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memmove ((void *) &b, x, sizeof (&b)); + memmove ((char *) &b, x, sizeof (&b)); + memmove (&b, x, sizeof (&b) + 0); + memmove (&b, x, 0 + sizeof (&b)); + + // These are correct, no warning. + memmove (x, &b, sizeof b); + memmove (x, &b, sizeof (b)); + memmove (x, &b, sizeof (struct B)); + memmove (x, &b, sizeof (const struct B)); + memmove (x, &b, sizeof (volatile struct B)); + memmove (x, &b, sizeof (volatile const struct B)); + memmove (x, &b, sizeof (TB)); + memmove (x, &b, sizeof (__typeof (*&b))); + memmove (x, pb1, sizeof (*pb1)); + memmove (x, pb2, sizeof (*pb3)); + memmove (x, pb3, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memmove (x, (void *) &b, sizeof (&b)); + memmove (x, (char *) &b, sizeof (&b)); + memmove (x, &b, sizeof (&b) + 0); + memmove (x, &b, 0 + sizeof (&b)); + + // These are correct, no warning. + z += memcmp (&b, x, sizeof b); + z += memcmp (&b, x, sizeof (b)); + z += memcmp (&b, x, sizeof (struct B)); + z += memcmp (&b, x, sizeof (const struct B)); + z += memcmp (&b, x, sizeof (volatile struct B)); + z += memcmp (&b, x, sizeof (volatile const struct B)); + z += memcmp (&b, x, sizeof (TB)); + z += memcmp (&b, x, sizeof (__typeof (*&b))); + z += memcmp (pb1, x, sizeof (*pb1)); + z += memcmp (pb2, x, sizeof (*pb3)); + z += memcmp (pb3, x, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp ((void *) &b, x, sizeof (&b)); + z += memcmp ((char *) &b, x, sizeof (&b)); + z += memcmp (&b, x, sizeof (&b) + 0); + z += memcmp (&b, x, 0 + sizeof (&b)); + + // These are correct, no warning. + z += memcmp (x, &b, sizeof b); + z += memcmp (x, &b, sizeof (b)); + z += memcmp (x, &b, sizeof (struct B)); + z += memcmp (x, &b, sizeof (const struct B)); + z += memcmp (x, &b, sizeof (volatile struct B)); + z += memcmp (x, &b, sizeof (volatile const struct B)); + z += memcmp (x, &b, sizeof (TB)); + z += memcmp (x, &b, sizeof (__typeof (*&b))); + z += memcmp (x, pb1, sizeof (*pb1)); + z += memcmp (x, pb2, sizeof (*pb3)); + z += memcmp (x, pb3, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp (x, (void *) &b, sizeof (&b)); + z += memcmp (x, (char *) &b, sizeof (&b)); + z += memcmp (x, &b, sizeof (&b) + 0); + z += memcmp (x, &b, 0 + sizeof (&b)); + + return z; +} + +int +f3 (void *x, char *y, int z, X w) +{ + unsigned char *y1 = (unsigned char *) __builtin_alloca (z + 16); + char buf1[7]; + signed char buf2[z + 32]; + long buf3[17]; + int *buf4[9]; + signed char *y2 = buf2; + char c; + char *y3; + memset (y, 0, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memset (y1, 0, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memset (y2, 0, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memset (&c, 0, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memset (w, 0, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + memcpy (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memcpy (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memcpy (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memcpy (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memcpy (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + memcpy (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memcpy (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memcpy (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memcpy (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memcpy (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + + memmove (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memmove (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memmove (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memmove (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memmove (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + memmove (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memmove (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memmove (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memmove (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memmove (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + + z += memcmp (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += memcmp (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += memcmp (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += memcmp (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + z += memcmp (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + z += memcmp (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += memcmp (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += memcmp (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += memcmp (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + z += memcmp (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + + // These are correct, no warning. + memset (y, 0, sizeof (*y)); + memset (y1, 0, sizeof (*y2)); + memset (buf1, 0, sizeof buf1); + memset (buf3, 0, sizeof (buf3)); + memset (&buf3[0], 0, sizeof (buf3)); + memset (&buf4[0], 0, sizeof (buf4)); + memset (w, 0, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memset ((void *) y, 0, sizeof (y)); + memset ((char *) y1, 0, sizeof (y2)); + memset (y, 0, sizeof (y) + 0); + memset (y1, 0, 0 + sizeof (y2)); + memset ((void *) &c, 0, sizeof (&c)); + memset ((signed char *) &c, 0, sizeof (&c)); + memset (&c, 0, sizeof (&c) + 0); + memset (&c, 0, 0 + sizeof (&c)); + + // These are correct, no warning. + memcpy (y, x, sizeof (*y)); + memcpy (y1, x, sizeof (*y2)); + memcpy (buf1, x, sizeof buf1); + memcpy (buf3, x, sizeof (buf3)); + memcpy (&buf3[0], x, sizeof (buf3)); + memcpy (&buf4[0], x, sizeof (buf4)); + memcpy (&y3, y, sizeof (y3)); + memcpy ((char *) &y3, y, sizeof (y3)); + memcpy (w, x, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memcpy ((void *) y, x, sizeof (y)); + memcpy ((char *) y1, x, sizeof (y2)); + memcpy (y, x, sizeof (y) + 0); + memcpy (y1, x, 0 + sizeof (y2)); + memcpy ((void *) &c, x, sizeof (&c)); + memcpy ((signed char *) &c, x, sizeof (&c)); + memcpy (&c, x, sizeof (&c) + 0); + memcpy (&c, x, 0 + sizeof (&c)); + + // These are correct, no warning. + memcpy (x, y, sizeof (*y)); + memcpy (x, y1, sizeof (*y2)); + memcpy (x, buf1, sizeof buf1); + memcpy (x, buf3, sizeof (buf3)); + memcpy (x, &buf3[0], sizeof (buf3)); + memcpy (x, &buf4[0], sizeof (buf4)); + memcpy (y, &y3, sizeof (y3)); + memcpy (y, (char *) &y3, sizeof (y3)); + memcpy (x, w, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memcpy (x, (void *) y, sizeof (y)); + memcpy (x, (char *) y1, sizeof (y2)); + memcpy (x, y, sizeof (y) + 0); + memcpy (x, y1, 0 + sizeof (y2)); + memcpy (x, (void *) &c, sizeof (&c)); + memcpy (x, (signed char *) &c, sizeof (&c)); + memcpy (x, &c, sizeof (&c) + 0); + memcpy (x, &c, 0 + sizeof (&c)); + + // These are correct, no warning. + memmove (y, x, sizeof (*y)); + memmove (y1, x, sizeof (*y2)); + memmove (buf1, x, sizeof buf1); + memmove (buf3, x, sizeof (buf3)); + memmove (&buf3[0], x, sizeof (buf3)); + memmove (&buf4[0], x, sizeof (buf4)); + memmove (&y3, y, sizeof (y3)); + memmove ((char *) &y3, y, sizeof (y3)); + memmove (w, x, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memmove ((void *) y, x, sizeof (y)); + memmove ((char *) y1, x, sizeof (y2)); + memmove (y, x, sizeof (y) + 0); + memmove (y1, x, 0 + sizeof (y2)); + memmove ((void *) &c, x, sizeof (&c)); + memmove ((signed char *) &c, x, sizeof (&c)); + memmove (&c, x, sizeof (&c) + 0); + memmove (&c, x, 0 + sizeof (&c)); + + // These are correct, no warning. + memmove (x, y, sizeof (*y)); + memmove (x, y1, sizeof (*y2)); + memmove (x, buf1, sizeof buf1); + memmove (x, buf3, sizeof (buf3)); + memmove (x, &buf3[0], sizeof (buf3)); + memmove (x, &buf4[0], sizeof (buf4)); + memmove (y, &y3, sizeof (y3)); + memmove (y, (char *) &y3, sizeof (y3)); + memmove (x, w, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memmove (x, (void *) y, sizeof (y)); + memmove (x, (char *) y1, sizeof (y2)); + memmove (x, y, sizeof (y) + 0); + memmove (x, y1, 0 + sizeof (y2)); + memmove (x, (void *) &c, sizeof (&c)); + memmove (x, (signed char *) &c, sizeof (&c)); + memmove (x, &c, sizeof (&c) + 0); + memmove (x, &c, 0 + sizeof (&c)); + + // These are correct, no warning. + z += memcmp (y, x, sizeof (*y)); + z += memcmp (y1, x, sizeof (*y2)); + z += memcmp (buf1, x, sizeof buf1); + z += memcmp (buf3, x, sizeof (buf3)); + z += memcmp (&buf3[0], x, sizeof (buf3)); + z += memcmp (&buf4[0], x, sizeof (buf4)); + z += memcmp (&y3, y, sizeof (y3)); + z += memcmp ((char *) &y3, y, sizeof (y3)); + z += memcmp (w, x, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + z += memcmp ((void *) y, x, sizeof (y)); + z += memcmp ((char *) y1, x, sizeof (y2)); + z += memcmp (y, x, sizeof (y) + 0); + z += memcmp (y1, x, 0 + sizeof (y2)); + z += memcmp ((void *) &c, x, sizeof (&c)); + z += memcmp ((signed char *) &c, x, sizeof (&c)); + z += memcmp (&c, x, sizeof (&c) + 0); + z += memcmp (&c, x, 0 + sizeof (&c)); + + // These are correct, no warning. + z += memcmp (x, y, sizeof (*y)); + z += memcmp (x, y1, sizeof (*y2)); + z += memcmp (x, buf1, sizeof buf1); + z += memcmp (x, buf3, sizeof (buf3)); + z += memcmp (x, &buf3[0], sizeof (buf3)); + z += memcmp (x, &buf4[0], sizeof (buf4)); + z += memcmp (y, &y3, sizeof (y3)); + z += memcmp (y, (char *) &y3, sizeof (y3)); + z += memcmp (x, w, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + z += memcmp (x, (void *) y, sizeof (y)); + z += memcmp (x, (char *) y1, sizeof (y2)); + z += memcmp (x, y, sizeof (y) + 0); + z += memcmp (x, y1, 0 + sizeof (y2)); + z += memcmp (x, (void *) &c, sizeof (&c)); + z += memcmp (x, (signed char *) &c, sizeof (&c)); + z += memcmp (x, &c, sizeof (&c) + 0); + z += memcmp (x, &c, 0 + sizeof (&c)); + + return z; +} + +int +f4 (char *x, char **y, int z) +{ + const char *s1 = "foobarbaz"; + const char *s2 = "abcde12345678"; + strncpy (x, s1, sizeof (s1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + strncat (x, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + y[0] = strndup (s1, sizeof (s1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += strncmp (s1, s2, sizeof (s1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += strncmp (s1, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += strncasecmp (s1, s2, sizeof (s1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += strncasecmp (s1, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + + // These are correct, no warning. + const char s3[] = "foobarbaz"; + const char s4[] = "abcde12345678"; + strncpy (x, s3, sizeof (s3)); + strncat (x, s4, sizeof (s4)); + y[1] = strndup (s3, sizeof (s3)); + z += strncmp (s3, s4, sizeof (s3)); + z += strncmp (s3, s4, sizeof (s4)); + z += strncasecmp (s3, s4, sizeof (s3)); + z += strncasecmp (s3, s4, sizeof (s4)); + + return z; +} + +// { dg-prune-output "\[\n\r\]*will always overflow\[\n\r\]*" } --- gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C.jj 2012-10-01 17:38:18.556576500 +0200 +++ gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C 2012-10-01 17:38:18.556576500 +0200 @@ -0,0 +1,13 @@ +// Test -Wsizeof-pointer-memaccess warnings. +// { dg-do compile } +// { dg-options "-Wall" } + +typedef __SIZE_TYPE__ size_t; +extern "C" void *memset (void *, int, size_t); + +int +foo (int x, char b[10]) +{ + long a[memset (b, 0, sizeof (b)) ? x + 10 : x]; // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length?" } + return a[0]; +} --- gcc/testsuite/g++.dg/warn/Wsign-compare-5.C.jj 2012-10-01 17:38:18.556576500 +0200 +++ gcc/testsuite/g++.dg/warn/Wsign-compare-5.C 2012-10-01 17:38:18.556576500 +0200 @@ -0,0 +1,20 @@ +// Test that -Wsign-compare doesn't warn about +// equality/non-equality comparisons with sizeof. +// { dg-do compile } +// { dg-options "-Wsign-compare" } + +int +foo (int x) +{ + if (x != sizeof (sizeof (x))) // { dg-bogus "comparison between signed and unsigned integer expressions" } + return 1; + return 0; +} + +int +bar (int x) +{ + if (x == sizeof (sizeof (x)) + 1) // { dg-bogus "comparison between signed and unsigned integer expressions" } + return 1; + return 0; +} --- gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C.jj 2011-05-02 18:39:10.000000000 +0200 +++ gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C 2012-10-02 10:32:08.764195850 +0200 @@ -9,7 +9,7 @@ void func2() { int* t = false; // { dg-warning "converting 'false' to pointer" } int* p; p = false; // { dg-warning "converting 'false' to pointer" } - int* r = sizeof(char) / 2; + int* r = sizeof(char) / 2; // { dg-error "invalid conversion from" "" { target c++11 } } func1(false); // { dg-warning "converting 'false' to pointer" } int i = NULL; // { dg-warning "converting to non-pointer" } } --- gcc/testsuite/g++.dg/ext/vla12.C.jj 2012-10-01 17:38:18.556576500 +0200 +++ gcc/testsuite/g++.dg/ext/vla12.C 2012-10-01 17:38:18.557576495 +0200 @@ -0,0 +1,28 @@ +// VLA sizeof test +// { dg-do compile } +// { dg-options "" } + +int +f1 (int i) +{ + char a[sizeof (i) + 6 + i]; + char b[sizeof (a) + 1]; + return sizeof (b); +} + +int +f2 (int i) +{ + char a[sizeof (i) + 6 + i]; + char b[sizeof (a)]; + return sizeof (b); +} + +int +f3 (int i) +{ + char a[sizeof (i) + 6 + i]; + char b[sizeof (i) + i]; + char c[sizeof (a) + sizeof (b) + 7]; + return sizeof (c); +} --- gcc/testsuite/g++.dg/ext/builtin30.C.jj 2012-10-01 17:38:18.557576495 +0200 +++ gcc/testsuite/g++.dg/ext/builtin30.C 2012-10-01 17:38:18.557576495 +0200 @@ -0,0 +1,27 @@ +// { dg-do compile } +// { dg-options "-O2" } + +typedef __SIZE_TYPE__ size_t; +extern "C" { +extern void __chk_fail (void); +extern int snprintf (char *, size_t, const char *, ...); +extern inline __attribute__((gnu_inline, always_inline)) int snprintf (char *a, size_t b, const char *fmt, ...) +{ + if (__builtin_object_size (a, 0) != -1UL && __builtin_object_size (a, 0) < b) + __chk_fail (); + return __builtin_snprintf (a, b, fmt, __builtin_va_arg_pack ()); +} +extern int snprintf (char *, size_t, const char *, ...) __asm ("mysnprintf"); +} + +char buf[10]; + +int +main (void) +{ + snprintf (buf, 10, "%d%d\n", 10, 10); + return 0; +} + +// { dg-final { scan-assembler "mysnprintf" } } +// { dg-final { scan-assembler-not "__chk_fail" } } --- gcc/testsuite/gcc.dg/builtins-85.c.jj 2012-10-01 17:38:18.557576495 +0200 +++ gcc/testsuite/gcc.dg/builtins-85.c 2012-10-01 17:38:18.557576495 +0200 @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef __SIZE_TYPE__ size_t; +extern void __chk_fail (void); +extern int snprintf (char *, size_t, const char *, ...); +extern inline __attribute__((gnu_inline, always_inline)) int snprintf (char *a, size_t b, const char *fmt, ...) +{ + if (__builtin_object_size (a, 0) != -1UL && __builtin_object_size (a, 0) < b) + __chk_fail (); + return __builtin_snprintf (a, b, fmt, __builtin_va_arg_pack ()); +} +extern int snprintf (char *, size_t, const char *, ...) __asm ("mysnprintf"); + +char buf[10]; + +int +main (void) +{ + snprintf (buf, 10, "%d%d\n", 10, 10); + return 0; +} + +/* { dg-final { scan-assembler "mysnprintf" } } */ +/* { dg-final { scan-assembler-not "__chk_fail" } } */ --- libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc.jj 2012-08-10 12:57:16.000000000 +0200 +++ libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc 2012-09-25 15:28:16.902924472 +0200 @@ -32,9 +32,9 @@ void test01() { X* px = 0; std::shared_ptr 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 } }