aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-12-20 11:31:18 +0100
committerJakub Jelinek <jakub@redhat.com>2023-12-20 11:31:18 +0100
commite7dd72aefed851d11655aa301d6e394ec9805e0d (patch)
tree72d1ccff1d2bd51c4c3cf7659feff2e4e80bcb7b /gcc/c
parentf5213759a7e0efc4ca7bbb484bab94ca19bc1b5d (diff)
downloadgcc-e7dd72aefed851d11655aa301d6e394ec9805e0d.zip
gcc-e7dd72aefed851d11655aa301d6e394ec9805e0d.tar.gz
gcc-e7dd72aefed851d11655aa301d6e394ec9805e0d.tar.bz2
c: Split -Wcalloc-transposed-args warning from -Walloc-size, -Walloc-size fixes
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). 2023-12-20 Jakub Jelinek <jakub@redhat.com> 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.
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/c-parser.cc15
-rw-r--r--gcc/c/c-typeck.cc44
2 files changed, 31 insertions, 28 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 4f1e066..c372430 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -12478,8 +12478,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
{
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<tree, va_gc> *exprlist;
@@ -12512,7 +12512,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
{
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_primary (c_parser *parser,
"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, bool convert_p, bool fold_p,
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))
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 022e3c63..a2164d9 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -6054,6 +6054,19 @@ build_c_cast (location_t loc, tree type, tree expr)
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 location, location_t expr_loc, tree type,
/* 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);