diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-12-21 11:17:08 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-12-21 11:17:08 +0100 |
commit | b9dc16cbe2222bf1006a6266ba89da460165f3cb (patch) | |
tree | dc9ea403efb11e0111bff4f30284df4dfece98cb | |
parent | 0e7f5039c52a020c3ed5f18a2b3ee1fb42b78f62 (diff) | |
download | gcc-b9dc16cbe2222bf1006a6266ba89da460165f3cb.zip gcc-b9dc16cbe2222bf1006a6266ba89da460165f3cb.tar.gz gcc-b9dc16cbe2222bf1006a6266ba89da460165f3cb.tar.bz2 |
c++: Enable -Walloc-size and -Wcalloc-transposed-args warnings for C++
The following patch enables the -Walloc-size and -Wcalloc-transposed-args
warnings for C++ as well.
Tracking just 6 arguments for SIZEOF_EXPR for the calloc purposes
is because I see alloc_size 1,2, 2,3 and 3,4 pairs used in the wild,
so we need at least 5 to cover that rather than 3, and don't want to waste
too much compile time/memory for that.
2023-12-21 Jakub Jelinek <jakub@redhat.com>
gcc/c-family/
* c.opt (Walloc-size): Enable also for C++ and ObjC++.
gcc/cp/
* cp-gimplify.cc (cp_genericize_r): If warn_alloc_size, call
warn_for_alloc_size for -Walloc-size diagnostics.
* semantics.cc (finish_call_expr): If warn_calloc_transposed_args,
call warn_for_calloc for -Wcalloc-transposed-args diagnostics.
gcc/testsuite/
* g++.dg/warn/Walloc-size-1.C: New test.
* g++.dg/warn/Wcalloc-transposed-args-1.C: New test.
-rw-r--r-- | gcc/c-family/c.opt | 2 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.cc | 19 | ||||
-rw-r--r-- | gcc/cp/semantics.cc | 29 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Walloc-size-1.C | 52 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wcalloc-transposed-args-1.C | 54 |
5 files changed, 148 insertions, 8 deletions
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 3faab7a..dbda1548 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -332,7 +332,7 @@ C ObjC C++ ObjC++ Var(warn_alloca) Warning Warn on any use of alloca. Walloc-size -C ObjC Var(warn_alloc_size) Warning LangEnabledBy(C ObjC, Wextra) +C ObjC C++ ObjC++ Var(warn_alloc_size) Warning LangEnabledBy(C ObjC C++ ObjC++, Wextra) Warn when allocating insufficient storage for the target type of the assigned pointer. Walloc-size-larger-than= diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index 64049f4..0ece9b0 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -2048,6 +2048,25 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) case NOP_EXPR: *stmt_p = predeclare_vla (*stmt_p); + + /* Warn of new allocations that are not big enough for the target + type. */ + if (warn_alloc_size + && TREE_CODE (TREE_OPERAND (stmt, 0)) == CALL_EXPR + && POINTER_TYPE_P (TREE_TYPE (stmt))) + { + if (tree fndecl = get_callee_fndecl (TREE_OPERAND (stmt, 0))) + 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 (EXPR_LOCATION (stmt), + TREE_TYPE (TREE_TYPE (stmt)), + TREE_OPERAND (stmt, 0), alloc_size); + } + } + if (!wtd->no_sanitize_p && sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT) && TYPE_REF_P (TREE_TYPE (stmt))) diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 64839b1..3370836 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -2939,15 +2939,24 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual, if (!result) { - if (warn_sizeof_pointer_memaccess + tree alloc_size_attr = NULL_TREE; + if (warn_calloc_transposed_args + && TREE_CODE (fn) == FUNCTION_DECL + && (alloc_size_attr + = lookup_attribute ("alloc_size", + TYPE_ATTRIBUTES (TREE_TYPE (fn))))) + if (TREE_VALUE (alloc_size_attr) == NULL_TREE + || TREE_CHAIN (TREE_VALUE (alloc_size_attr)) == NULL_TREE) + alloc_size_attr = NULL_TREE; + if ((warn_sizeof_pointer_memaccess || alloc_size_attr) && (complain & tf_warning) && !vec_safe_is_empty (*args) && !processing_template_decl) { - location_t sizeof_arg_loc[3]; - tree sizeof_arg[3]; + location_t sizeof_arg_loc[6]; + tree sizeof_arg[6]; unsigned int i; - for (i = 0; i < 3; i++) + for (i = 0; i < (alloc_size_attr ? 6 : 3); i++) { tree t; @@ -2964,9 +2973,15 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual, sizeof_arg[i] = TREE_OPERAND (t, 0); sizeof_arg_loc[i] = EXPR_LOCATION (t); } - sizeof_pointer_memaccess_warning - (sizeof_arg_loc, fn, *args, - sizeof_arg, same_type_ignoring_top_level_qualifiers_p); + if (warn_sizeof_pointer_memaccess) + { + auto same_p = same_type_ignoring_top_level_qualifiers_p; + sizeof_pointer_memaccess_warning (sizeof_arg_loc, fn, *args, + sizeof_arg, same_p); + } + if (alloc_size_attr) + warn_for_calloc (sizeof_arg_loc, fn, *args, sizeof_arg, + alloc_size_attr); } if ((complain & tf_warning) diff --git a/gcc/testsuite/g++.dg/warn/Walloc-size-1.C b/gcc/testsuite/g++.dg/warn/Walloc-size-1.C new file mode 100644 index 0000000..3a3f3b0 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Walloc-size-1.C @@ -0,0 +1,52 @@ +// 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 (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) +{ + S *p = (S *) __builtin_malloc (sizeof *p); + __builtin_free (p); + p = (S *) __builtin_malloc (sizeof p); // { dg-warning "allocation of insufficient size" } + __builtin_free (p); + p = (S *) __builtin_alloca (sizeof p); // { dg-warning "allocation of insufficient size" } + bar (p); + p = (S *) __builtin_calloc (1, sizeof p); // { dg-warning "allocation of insufficient size" } + __builtin_free (p); + bar ((S *) __builtin_malloc (4)); // { dg-warning "allocation of insufficient size" } + __builtin_free (p); + p = (S *) __builtin_calloc (sizeof *p, 1); + __builtin_free (p); +} + +void +baz (void) +{ + S *p = (S *) mymalloc (42, 42, sizeof *p); + myfree (p, 42, 42); + p = (S *) mymalloc (42, 42, sizeof p); // { dg-warning "allocation of insufficient size" } + myfree (p, 42, 42); + p = (S *) mycalloc (42, 42, 1, sizeof p); // { dg-warning "allocation of insufficient size" } + myfree (p, 42, 42); + bar ((S *) mymalloc (42, 42, 4)); // { dg-warning "allocation of insufficient size" } + myfree (p, 42, 42); + p = (S *) mycalloc (42, 42, sizeof *p, 1); + myfree (p, 42, 42); + p = static_cast <S *> (mycalloc (42, 42, sizeof *p, 1)); + myfree (p, 42, 42); + p = static_cast <S *> (mymalloc (42, 42, sizeof *p)); + myfree (p, 42, 42); + p = static_cast <S *> (mymalloc (42, 42, sizeof p)); // { dg-warning "allocation of insufficient size" } + myfree (p, 42, 42); + p = static_cast <S *> (mycalloc (42, 42, 1, sizeof p)); // { dg-warning "allocation of insufficient size" } + myfree (p, 42, 42); + bar (static_cast <S *> (mymalloc (42, 42, 4))); // { dg-warning "allocation of insufficient size" } + myfree (p, 42, 42); +} diff --git a/gcc/testsuite/g++.dg/warn/Wcalloc-transposed-args-1.C b/gcc/testsuite/g++.dg/warn/Wcalloc-transposed-args-1.C new file mode 100644 index 0000000..fa60583 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wcalloc-transposed-args-1.C @@ -0,0 +1,54 @@ +// { dg-do compile } +// { dg-options "-Wcalloc-transposed-args" } + +typedef __SIZE_TYPE__ size_t; +extern "C" void free (void *); +extern "C" 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); +} |