aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family
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-family
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-family')
-rw-r--r--gcc/c-family/c-common.h3
-rw-r--r--gcc/c-family/c-warn.cc70
-rw-r--r--gcc/c-family/c.opt4
3 files changed, 77 insertions, 0 deletions
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index b8bd56c..925e7af 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1599,6 +1599,9 @@ extern void warn_about_parentheses (location_t,
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, va_gc> *,
+ 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,
diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index abe66dd..69621bf 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -2263,6 +2263,76 @@ warn_for_memset (location_t loc, tree arg0, tree arg2,
}
}
+/* Warn for calloc (sizeof (X), n). */
+
+void
+warn_for_calloc (location_t *sizeof_arg_loc, tree callee,
+ vec<tree, va_gc> *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 %<sizeof%> 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,
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 03b64d5..3faab7a 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -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.