From patchwork Mon Dec 18 19:14:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 180626 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:24d3:b0:fb:cd0c:d3e with SMTP id r19csp1472624dyi; Mon, 18 Dec 2023 11:15:18 -0800 (PST) X-Google-Smtp-Source: AGHT+IGBwwnKZbI8UvmAypB83enGqBY3NiRlKI7JnyU1rK39q/CVX4Kt3r/g88Ecrwr972PU11Jl X-Received: by 2002:a05:6870:c4b:b0:1ef:bacc:e4d2 with SMTP id lf11-20020a0568700c4b00b001efbacce4d2mr17777877oab.28.1702926918410; Mon, 18 Dec 2023 11:15:18 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1702926918; cv=pass; d=google.com; s=arc-20160816; b=A6lVGfarZLvrYdl3zwGWPDrxRqDgutG2wqMyTqQo7hc5RZ9NvDw4yEzbM9B6BBovkW iFIUAlj7jAqT4I+iu4CPYulNhyfsTJUfjvhJaZ4rSYxTt5iplmwg2YjcRIj1mdoq4NjI 5QJ3zhxB+F0xvyIUc5I0yY5VefZIuyogCXXSMlhfF6kz4zKr4cx2BTlRUTvwWakDTK6J zNzzXcHTAx3NPVunuXvzMuX1RLkOSiCMPhAknXd12umJOXDpSofKrKCTVQofreos/TSA Isl8pWx59esUa0Ev2irZs86Y8ZetesN9i21Rc8X+465pqHsxN/FY+YTbJ2pK0F7tU0yX Q6kA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:reply-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-disposition :mime-version:message-id:subject:cc:to:from:date:dkim-signature :arc-filter:dmarc-filter:delivered-to; bh=zGEFrcV8ZmiU/GxEkkopRdVoh2yBqpeZtw7pUDgnFJM=; fh=hx7BFWQv7T4+699ZC52YTNHro0AfIvqYSgCe5g07GEs=; b=Mq6txd/ETVIL9eFNuqzfWAiNDbaM2+nM4dIiWb4Nl9VOxqg/AE9OaAXr7fVX/Sq/Mt M+W4QN2r5FYNJ2lA2/VofGN88wxQnl/aOo78o7/3fVuvW7Qj/cPX26YMDDR7bKfnQ2uI zsJm8ewTFFB/OEbU93zFdO1phEJz9qafXpxc7ZKo7WeFNbxBnKKL2N3JfVZAjNl1zH9b wDeD0Ghj+lI5/+QcIK1NFSv0cVVL3LSA+7FU2Zctr4qXETSguG3hvryWY5Jzq4qyBYsK XEZJmEPJv0RNpy9e0cZpscA6Q6+yiTHZ8llcJPiDMfbMKfg01XLo8+UOigG28pOs53jy psxg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=OLtbmbBE; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id u18-20020a05620a121200b0077dc62e66f2si23593019qkj.603.2023.12.18.11.15.17 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 18 Dec 2023 11:15:18 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=OLtbmbBE; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C51A73857346 for ; Mon, 18 Dec 2023 19:15:17 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 7F01E3858028 for ; Mon, 18 Dec 2023 19:14:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7F01E3858028 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 7F01E3858028 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702926895; cv=none; b=BRaONgVkR1tdTZfFrmMrmrVhONGqRTityi3ENS9k//8M02LIq28nAvXOihhR5l62x9ycGrIznPP+HOtAoMokv2O5l0h6j6fqYC939DwFbqVlEo8cS8OX3iIZatwgCRmz5hAxr7CqZ2RhMm82BIkFb4Ua3MsrDtmnCArc90eozmQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702926895; c=relaxed/simple; bh=M3Gn6cMj0o7rq8ptregiPhHgCl7LumzhEoc+0snctYM=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=TPXFJg74klPNSOUiqlNq0nvGmikOWVukb+6e3NDiQ0DQLp8KSCpUnkQVCiCYBC4OrYPxrHySVxzBI0nagh5OACuxHYAd4EqZ7PF1gEYKtw11PQp4IHYulscG992HHSqfb7yCu+pcL0uv0JVvWTrMHQ83SF+6YArPhhaPUiMVFZ8= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702926892; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type; bh=zGEFrcV8ZmiU/GxEkkopRdVoh2yBqpeZtw7pUDgnFJM=; b=OLtbmbBEarT4SyZuGzEKNhR0NH6YbxjW9rpb89dMlBgAjQvtHZWDB2N9w/IJdqfanAtiIj kCuuhWezDNsBIYnsM0/kTWhqCEXJjfzFdxtq/Mm7gGwEGE/Qp9blFXNMxr6WaA9V6wH+0m gkhE3vwsvyedPkltkbmZ0sEGN3kPj2Q= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-358-iqV88hYkO9q3TTSxNDx3AQ-1; Mon, 18 Dec 2023 14:14:48 -0500 X-MC-Unique: iqV88hYkO9q3TTSxNDx3AQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 68EE23C0F363; Mon, 18 Dec 2023 19:14:48 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.92]) by smtp.corp.redhat.com (Postfix) with ESMTPS id DD2122166B31; Mon, 18 Dec 2023 19:14:47 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 3BIJEiKE1299864 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 18 Dec 2023 20:14:45 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 3BIJEhFe1299863; Mon, 18 Dec 2023 20:14:43 +0100 Date: Mon, 18 Dec 2023 20:14:42 +0100 From: Jakub Jelinek To: "Joseph S. Myers" , Marek Polacek , Jason Merrill , Richard Biener , Martin Uecker Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c: Split -Wcalloc-transposed-args warning from -Walloc-size, -Walloc-size fixes Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1785648296340504997 X-GMAIL-MSGID: 1785648296340504997 Hi! The following patch changes -Walloc-size warning to no longer warn about int *p = calloc (1, sizeof (int));, because as discussed earlier, the size is IMNSHO sufficient in that case, for alloc_size with 2 arguments warns if the product of the 2 arguments is insufficiently small. Also, it warns also for explicit casts of malloc/calloc etc. calls rather than just implicit, so not just int *p = malloc (1); but also int *p = (int *) malloc (1); It also fixes some ICEs where the code didn't verify the alloc_size arguments properly (Walloc-size-5.c testcase ICEs with vanilla trunk). And lastly, it introduces a coding style warning, -Wcalloc-transposed-args to warn for calloc (sizeof (struct S), 1) and similar calls (regardless of what they are cast to, warning whenever first argument is sizeof and the second is not). Ok for trunk if this passes bootstrap/regtest? If yes, I'd implement it for C++ next. If not, we should at least fix the ICEs. 2023-12-18 Jakub Jelinek gcc/ * doc/invoke.texi (-Walloc-size): Add to the list of warning options, remove unnecessary line-break. (-Wcalloc-transposed-args): Document new warning. gcc/c-family/ * c.opt (Wcalloc-transposed-args): New warning. * c-common.h (warn_for_calloc, warn_for_alloc_size): Declare. * c-warn.cc (warn_for_calloc, warn_for_alloc_size): New functions. gcc/c/ * c-parser.cc (c_parser_postfix_expression_after_primary): Grow sizeof_arg and sizeof_arg_loc arrays to 6 elements. Call warn_for_calloc if warn_calloc_transposed_args for functions with alloc_size type attribute with 2 arguments. (c_parser_expr_list): Use 6 instead of 3. * c-typeck.cc (build_c_cast): Call warn_for_alloc_size for casts of calls to functions with alloc_size type attribute. (convert_for_assignment): Likewise. gcc/testsuite/ * gcc.dg/Walloc-size-4.c: New test. * gcc.dg/Walloc-size-5.c: New test. * gcc.dg/Wcalloc-transposed-args-1.c: New test. Jakub --- gcc/doc/invoke.texi.jj 2023-12-18 09:39:49.411355496 +0100 +++ gcc/doc/invoke.texi 2023-12-18 19:59:37.139525128 +0100 @@ -328,7 +328,7 @@ Objective-C and Objective-C++ Dialects}. -pedantic-errors -fpermissive -w -Wextra -Wall -Wabi=@var{n} -Waddress -Wno-address-of-packed-member -Waggregate-return --Walloc-size-larger-than=@var{byte-size} -Walloc-zero +-Walloc-size -Walloc-size-larger-than=@var{byte-size} -Walloc-zero -Walloca -Walloca-larger-than=@var{byte-size} -Wno-aggressive-loop-optimizations -Warith-conversion @@ -344,6 +344,7 @@ Objective-C and Objective-C++ Dialects}. -Wc++20-compat -Wno-c++11-extensions -Wno-c++14-extensions -Wno-c++17-extensions -Wno-c++20-extensions -Wno-c++23-extensions +-Wcalloc-transposed-args -Wcast-align -Wcast-align=strict -Wcast-function-type -Wcast-qual -Wchar-subscripts -Wclobbered -Wcomment @@ -8260,8 +8261,7 @@ Warn about calls to allocation functions @code{alloc_size} that specify insufficient size for the target type of the pointer the result is assigned to, including those to the built-in forms of the functions @code{aligned_alloc}, @code{alloca}, -@code{calloc}, -@code{malloc}, and @code{realloc}. +@code{calloc}, @code{malloc}, and @code{realloc}. @opindex Wno-alloc-zero @opindex Walloc-zero @@ -8274,6 +8274,21 @@ when called with a zero size differs amo of @code{realloc} has been deprecated) relying on it may result in subtle portability bugs and should be avoided. +@opindex Wcalloc-transposed-args +@opindex Wno-calloc-transposed-args +@item -Wcalloc-transposed-args +Warn about calls to allocation functions decorated with attribute +@code{alloc_size} with two arguments, which use @code{sizeof} operator +as the earlier size argument and don't use it as the later size argument. +This is a coding style warning. The first argument to @code{calloc} is +documented to be number of elements in array, while the second argument +is size of each element, so @code{calloc (@var{n}, sizeof (int))} is preferred +over @code{calloc (sizeof (int), @var{n})}. If @code{sizeof} in the earlier +argument and not the latter is intentional, the warning can be suppressed +by using @code{calloc (sizeof (struct @var{S}) + 0, n)} or +@code{calloc (1 * sizeof (struct @var{S}), 4)} or using @code{sizeof} in the +later argument as well. + @opindex Walloc-size-larger-than= @opindex Wno-alloc-size-larger-than @item -Walloc-size-larger-than=@var{byte-size} --- gcc/c-family/c.opt.jj 2023-12-14 07:49:52.951583511 +0100 +++ gcc/c-family/c.opt 2023-12-18 13:57:11.834184689 +0100 @@ -502,6 +502,10 @@ Wc++26-extensions C++ ObjC++ Var(warn_cxx26_extensions) Warning Init(1) Warn about C++26 constructs in code compiled with an older standard. +Wcalloc-transposed-args +C ObjC C++ ObjC++ Var(warn_calloc_transposed_args) Warning LangEnabledBy(C ObjC C++ ObjC++,Wextra) +Warn about suspicious calls to calloc-like functions where sizeof expression is the earlier size argument and not the latter. + Wcast-function-type C ObjC C++ ObjC++ Var(warn_cast_function_type) Warning EnabledBy(Wextra) Warn about casts between incompatible function types. --- gcc/c-family/c-common.h.jj 2023-12-14 07:49:52.915584002 +0100 +++ gcc/c-family/c-common.h 2023-12-18 16:26:40.420196735 +0100 @@ -1599,6 +1599,9 @@ extern void warn_about_parentheses (loca extern void warn_for_unused_label (tree label); extern void warn_for_div_by_zero (location_t, tree divisor); extern void warn_for_memset (location_t, tree, tree, int); +extern void warn_for_calloc (location_t *, tree, vec *, + tree *, tree); +extern void warn_for_alloc_size (location_t, tree, tree, tree); extern void warn_for_sign_compare (location_t, tree orig_op0, tree orig_op1, tree op0, tree op1, --- gcc/c-family/c-warn.cc.jj 2023-12-14 07:49:52.951583511 +0100 +++ gcc/c-family/c-warn.cc 2023-12-18 19:30:47.285607029 +0100 @@ -2263,6 +2263,76 @@ warn_for_memset (location_t loc, tree ar } } +/* Warn for calloc (sizeof (X), n). */ + +void +warn_for_calloc (location_t *sizeof_arg_loc, tree callee, + vec *params, tree *sizeof_arg, tree attr) +{ + if (!TREE_VALUE (attr) || !TREE_CHAIN (TREE_VALUE (attr))) + return; + + int arg1 = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))) - 1; + int arg2 + = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (TREE_VALUE (attr)))) - 1; + if (arg1 < 0 + || (unsigned) arg1 >= vec_safe_length (params) + || arg1 >= 6 + || arg2 < 0 + || (unsigned) arg2 >= vec_safe_length (params) + || arg2 >= 6 + || arg1 >= arg2) + return; + + if (sizeof_arg[arg1] == NULL_TREE || sizeof_arg[arg2] != NULL_TREE) + return; + + if (warning_at (sizeof_arg_loc[arg1], OPT_Wcalloc_transposed_args, + "%qD sizes specified with % in the earlier " + "argument and not in the later argument", callee)) + inform (sizeof_arg_loc[arg1], "earlier argument should specify number " + "of elements, later size of each element"); +} + +/* Warn for allocator calls where the constant allocated size is smaller + than sizeof (TYPE). */ + +void +warn_for_alloc_size (location_t loc, tree type, tree call, tree alloc_size) +{ + if (!TREE_VALUE (alloc_size)) + return; + + tree arg1 = TREE_VALUE (TREE_VALUE (alloc_size)); + int idx1 = TREE_INT_CST_LOW (arg1) - 1; + if (idx1 < 0 || idx1 >= call_expr_nargs (call)) + return; + arg1 = CALL_EXPR_ARG (call, idx1); + if (TREE_CODE (arg1) != INTEGER_CST) + return; + if (TREE_CHAIN (TREE_VALUE (alloc_size))) + { + tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_VALUE (alloc_size))); + int idx2 = TREE_INT_CST_LOW (arg2) - 1; + if (idx2 < 0 || idx2 >= call_expr_nargs (call)) + return; + arg2 = CALL_EXPR_ARG (call, idx2); + if (TREE_CODE (arg2) != INTEGER_CST) + return; + arg1 = int_const_binop (MULT_EXPR, fold_convert (sizetype, arg1), + fold_convert (sizetype, arg2)); + if (TREE_CODE (arg1) != INTEGER_CST) + return; + } + if (!VOID_TYPE_P (type) + && TYPE_SIZE_UNIT (type) + && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST + && tree_int_cst_lt (arg1, TYPE_SIZE_UNIT (type))) + warning_at (loc, OPT_Walloc_size, + "allocation of insufficient size %qE for type %qT with " + "size %qE", arg1, type, TYPE_SIZE_UNIT (type)); +} + /* Subroutine of build_binary_op. Give warnings for comparisons between signed and unsigned quantities that may fail. Do the checking based on the original operand trees ORIG_OP0 and ORIG_OP1, --- gcc/c/c-parser.cc.jj 2023-12-14 07:49:52.969583266 +0100 +++ gcc/c/c-parser.cc 2023-12-18 19:24:01.508298779 +0100 @@ -12478,8 +12478,8 @@ c_parser_postfix_expression_after_primar { struct c_expr orig_expr; tree ident, idx; - location_t sizeof_arg_loc[3], comp_loc; - tree sizeof_arg[3]; + location_t sizeof_arg_loc[6], comp_loc; + tree sizeof_arg[6]; unsigned int literal_zero_mask; unsigned int i; vec *exprlist; @@ -12512,7 +12512,7 @@ c_parser_postfix_expression_after_primar { matching_parens parens; parens.consume_open (parser); - for (i = 0; i < 3; i++) + for (i = 0; i < 6; i++) { sizeof_arg[i] = NULL_TREE; sizeof_arg_loc[i] = UNKNOWN_LOCATION; @@ -12577,6 +12577,13 @@ c_parser_postfix_expression_after_primar "not permitted in intervening code"); parser->omp_for_parse_state->fail = true; } + if (warn_calloc_transposed_args) + if (tree attr = lookup_attribute ("alloc_size", + TYPE_ATTRIBUTES + (TREE_TYPE (expr.value)))) + if (TREE_VALUE (attr) && TREE_CHAIN (TREE_VALUE (attr))) + warn_for_calloc (sizeof_arg_loc, expr.value, exprlist, + sizeof_arg, attr); } start = expr.get_start (); @@ -12861,7 +12868,7 @@ c_parser_expr_list (c_parser *parser, bo vec_safe_push (orig_types, expr.original_type); if (locations) locations->safe_push (expr.get_location ()); - if (++idx < 3 + if (++idx < 6 && sizeof_arg != NULL && (expr.original_code == SIZEOF_EXPR || expr.original_code == PAREN_SIZEOF_EXPR)) --- gcc/c/c-typeck.cc.jj 2023-12-14 07:49:52.990582980 +0100 +++ gcc/c/c-typeck.cc 2023-12-18 19:01:40.013746860 +0100 @@ -6054,6 +6054,19 @@ build_c_cast (location_t loc, tree type, c_addr_space_name (as_to), c_addr_space_name (as_from)); } + + /* Warn of new allocations that are not big enough for the target + type. */ + if (warn_alloc_size && TREE_CODE (value) == CALL_EXPR) + if (tree fndecl = get_callee_fndecl (value)) + if (DECL_IS_MALLOC (fndecl)) + { + tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (fndecl)); + tree alloc_size = lookup_attribute ("alloc_size", attrs); + if (alloc_size) + warn_for_alloc_size (loc, TREE_TYPE (type), value, + alloc_size); + } } /* Warn about possible alignment problems. */ @@ -7277,32 +7290,15 @@ convert_for_assignment (location_t locat /* Warn of new allocations that are not big enough for the target type. */ - tree fndecl; - if (warn_alloc_size - && TREE_CODE (rhs) == CALL_EXPR - && (fndecl = get_callee_fndecl (rhs)) != NULL_TREE - && DECL_IS_MALLOC (fndecl)) - { - tree fntype = TREE_TYPE (fndecl); - tree fntypeattrs = TYPE_ATTRIBUTES (fntype); - tree alloc_size = lookup_attribute ("alloc_size", fntypeattrs); - if (alloc_size) + if (warn_alloc_size && TREE_CODE (rhs) == CALL_EXPR) + if (tree fndecl = get_callee_fndecl (rhs)) + if (DECL_IS_MALLOC (fndecl)) { - tree args = TREE_VALUE (alloc_size); - int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1; - /* For calloc only use the second argument. */ - if (TREE_CHAIN (args)) - idx = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1; - tree arg = CALL_EXPR_ARG (rhs, idx); - if (TREE_CODE (arg) == INTEGER_CST - && !VOID_TYPE_P (ttl) && TYPE_SIZE_UNIT (ttl) - && INTEGER_CST == TREE_CODE (TYPE_SIZE_UNIT (ttl)) - && tree_int_cst_lt (arg, TYPE_SIZE_UNIT (ttl))) - warning_at (location, OPT_Walloc_size, "allocation of " - "insufficient size %qE for type %qT with " - "size %qE", arg, ttl, TYPE_SIZE_UNIT (ttl)); + tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (fndecl)); + tree alloc_size = lookup_attribute ("alloc_size", attrs); + if (alloc_size) + warn_for_alloc_size (location, ttl, rhs, alloc_size); } - } /* See if the pointers point to incompatible address spaces. */ asl = TYPE_ADDR_SPACE (ttl); --- gcc/testsuite/gcc.dg/Walloc-size-4.c.jj 2023-12-18 19:06:41.069528176 +0100 +++ gcc/testsuite/gcc.dg/Walloc-size-4.c 2023-12-18 19:34:06.964824180 +0100 @@ -0,0 +1,54 @@ +/* Tests the warnings for insufficient allocation size. */ +/* { dg-do compile } */ +/* { dg-options "-Walloc-size -Wno-calloc-transposed-args" } */ + +struct S { int x[10]; }; +void bar (struct S *); +typedef __SIZE_TYPE__ size_t; +void *myfree (void *, int, int); +void *mymalloc (int, int, size_t) __attribute__((malloc, malloc (myfree), alloc_size (3))); +void *mycalloc (int, int, size_t, size_t) __attribute__((malloc, malloc (myfree), alloc_size (3, 4))); + +void +foo (void) +{ + struct S *p = (struct S *) __builtin_malloc (sizeof *p); + __builtin_free (p); + p = (struct S *) __builtin_malloc (sizeof p); /* { dg-warning "allocation of insufficient size" } */ + __builtin_free (p); + p = (struct S *) __builtin_alloca (sizeof p); /* { dg-warning "allocation of insufficient size" } */ + bar (p); + p = (struct S *) __builtin_calloc (1, sizeof p); /* { dg-warning "allocation of insufficient size" } */ + __builtin_free (p); + bar ((struct S *) __builtin_malloc (4)); /* { dg-warning "allocation of insufficient size" } */ + __builtin_free (p); + p = (struct S *) __builtin_calloc (sizeof *p, 1); + __builtin_free (p); + p = __builtin_calloc (sizeof *p, 1); + __builtin_free (p); +} + +void +baz (void) +{ + struct S *p = (struct S *) mymalloc (42, 42, sizeof *p); + myfree (p, 42, 42); + p = (struct S *) mymalloc (42, 42, sizeof p); /* { dg-warning "allocation of insufficient size" } */ + myfree (p, 42, 42); + p = (struct S *) mycalloc (42, 42, 1, sizeof p); /* { dg-warning "allocation of insufficient size" } */ + myfree (p, 42, 42); + bar ((struct S *) mymalloc (42, 42, 4)); /* { dg-warning "allocation of insufficient size" } */ + myfree (p, 42, 42); + p = (struct S *) mycalloc (42, 42, sizeof *p, 1); + myfree (p, 42, 42); + p = mycalloc (42, 42, sizeof *p, 1); + myfree (p, 42, 42); + p = mymalloc (42, 42, sizeof *p); + myfree (p, 42, 42); + p = mymalloc (42, 42, sizeof p); /* { dg-warning "allocation of insufficient size" } */ + myfree (p, 42, 42); + p = mycalloc (42, 42, 1, sizeof p); /* { dg-warning "allocation of insufficient size" } */ + myfree (p, 42, 42); + bar (mymalloc (42, 42, 4)); /* { dg-warning "allocation of insufficient size" } */ + myfree (p, 42, 42); +} --- gcc/testsuite/gcc.dg/Walloc-size-5.c.jj 2023-12-18 19:18:13.451180896 +0100 +++ gcc/testsuite/gcc.dg/Walloc-size-5.c 2023-12-18 19:19:25.244173868 +0100 @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-Walloc-size -std=gnu11" } */ + +struct S { int x[10]; }; +void myfree (); +void *mymalloc () __attribute__((malloc, alloc_size (16))); +void *mycalloc () __attribute__((malloc, alloc_size (16, 17))); + +void +foo (void) +{ + struct S *p = mymalloc (1); + myfree (p); + p = mycalloc (1, 1); + myfree (p); + p = (struct S *) mymalloc (1); + myfree (p); + p = (struct S *) mycalloc (1, 1); + myfree (p); +} --- gcc/testsuite/gcc.dg/Wcalloc-transposed-args-1.c.jj 2023-12-18 19:39:42.930196797 +0100 +++ gcc/testsuite/gcc.dg/Wcalloc-transposed-args-1.c 2023-12-18 19:52:03.273855456 +0100 @@ -0,0 +1,54 @@ +/* { dg-do compile } */ +/* { dg-options "-Wcalloc-transposed-args" } */ + +typedef __SIZE_TYPE__ size_t; +void free (void *); +void *calloc (size_t, size_t); +void *myfree (void *, int, int); +void *mycalloc (int, int, size_t, size_t) __attribute__((malloc, malloc (myfree), alloc_size (3, 4))); + +void +foo (int n) +{ + void *p; + p = __builtin_calloc (1, sizeof (int)); + __builtin_free (p); + p = __builtin_calloc (n, sizeof (int)); + __builtin_free (p); + p = __builtin_calloc (sizeof (int), 1); /* { dg-warning "'__builtin_calloc' sizes specified with 'sizeof' in the earlier argument and not in the later argument" } */ + __builtin_free (p); /* { dg-message "earlier argument should specify number of elements, later size of each element" "" { target *-*-* } .-1 } */ + p = __builtin_calloc (sizeof (int), n); /* { dg-warning "'__builtin_calloc' sizes specified with 'sizeof' in the earlier argument and not in the later argument" } */ + __builtin_free (p); /* { dg-message "earlier argument should specify number of elements, later size of each element" "" { target *-*-* } .-1 } */ + p = __builtin_calloc ((sizeof (int)), 1); /* { dg-warning "'__builtin_calloc' sizes specified with 'sizeof' in the earlier argument and not in the later argument" } */ + __builtin_free (p); /* { dg-message "earlier argument should specify number of elements, later size of each element" "" { target *-*-* } .-1 } */ + p = __builtin_calloc (sizeof (int) + 0, 1); + __builtin_free (p); + p = __builtin_calloc (sizeof (int), sizeof (char)); + __builtin_free (p); + p = __builtin_calloc (1 * sizeof (int), 1); + __builtin_free (p); + p = calloc (1, sizeof (int)); + free (p); + p = calloc (n, sizeof (int)); + free (p); + p = calloc (sizeof (int), 1); /* { dg-warning "'calloc' sizes specified with 'sizeof' in the earlier argument and not in the later argument" } */ + free (p); /* { dg-message "earlier argument should specify number of elements, later size of each element" "" { target *-*-* } .-1 } */ + p = calloc (sizeof (int), n); /* { dg-warning "'calloc' sizes specified with 'sizeof' in the earlier argument and not in the later argument" } */ + free (p); /* { dg-message "earlier argument should specify number of elements, later size of each element" "" { target *-*-* } .-1 } */ + p = calloc (sizeof (int), sizeof (char)); + free (p); + p = calloc (1 * sizeof (int), 1); + free (p); + p = mycalloc (42, 42, 1, sizeof (int)); + myfree (p, 42, 42); + p = mycalloc (42, 42, n, sizeof (int)); + myfree (p, 42, 42); + p = mycalloc (42, 42, sizeof (int), 1); /* { dg-warning "'mycalloc' sizes specified with 'sizeof' in the earlier argument and not in the later argument" } */ + myfree (p, 42, 42); /* { dg-message "earlier argument should specify number of elements, later size of each element" "" { target *-*-* } .-1 } */ + p = mycalloc (42, 42, sizeof (int), n); /* { dg-warning "'mycalloc' sizes specified with 'sizeof' in the earlier argument and not in the later argument" } */ + myfree (p, 42, 42); /* { dg-message "earlier argument should specify number of elements, later size of each element" "" { target *-*-* } .-1 } */ + p = mycalloc (42, 42, sizeof (int), sizeof (char)); + myfree (p, 42, 42); + p = mycalloc (42, 42, 1 * sizeof (int), 1); + myfree (p, 42, 42); +}