diff options
author | Jakub Jelinek <jakub@redhat.com> | 2012-08-17 09:17:56 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-08-17 09:17:56 +0200 |
commit | 1a4049e7c504bedf3f485fd94a26902959a4ce2a (patch) | |
tree | 4109785fceb3bc788cf4f9ee1e8a0fc71649fdfb /gcc/c-family | |
parent | 138f5acd18aafd07cd4a034cb8e879dd0621544b (diff) | |
download | gcc-1a4049e7c504bedf3f485fd94a26902959a4ce2a.zip gcc-1a4049e7c504bedf3f485fd94a26902959a4ce2a.tar.gz gcc-1a4049e7c504bedf3f485fd94a26902959a4ce2a.tar.bz2 |
invoke.texi (-Wsizeof-pointer-memaccess): Document.
* doc/invoke.texi (-Wsizeof-pointer-memaccess): Document.
c/
* c-tree.h (c_last_sizeof_arg): Declare.
* c-parser.c (struct c_tree_loc_pair): New type.
(c_parser_expr_list): Add sizeof_arg argument. Fill it in if
non-NULL.
(c_parser_attributes, c_parser_objc_keywordexpr): Adjust callers.
(c_parser_postfix_expression_after_primary): Likewise. Call
sizeof_pointer_memaccess_warning if needed.
(sizeof_ptr_memacc_comptypes): New function.
* c-typeck.c (c_last_sizeof_arg): New global variable.
(c_expr_sizeof_expr, c_expr_sizeof_type): Initialize it.
cp/
* cp-tree.def (SIZEOF_EXPR): Move to c-common.def.
c-family/
* c-common.c (sizeof_pointer_memaccess_warning): New function.
* c.opt (-Wsizeof-pointer-memaccess): Add new option.
* c-opts.c (c_common_handle_option): Enable it for -Wall.
* c-common.h (sizeof_pointer_memaccess_warning): Add prototype.
* c-common.def (SIZEOF_EXPR): Moved here from cp-tree.def.
fortran/
* array.c (gfc_match_array_ref): Fix up memset arguments.
testsuite/
* gcc.dg/torture/Wsizeof-pointer-memaccess1.c: New test.
From-SVN: r190467
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 143 | ||||
-rw-r--r-- | gcc/c-family/c-common.def | 6 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 7 | ||||
-rw-r--r-- | gcc/c-family/c-opts.c | 5 | ||||
-rw-r--r-- | gcc/c-family/c.opt | 3 |
6 files changed, 167 insertions, 5 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index c460b35..2ce3f59 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,11 @@ +2012-08-17 Jakub Jelinek <jakub@redhat.com> + + * c-common.c (sizeof_pointer_memaccess_warning): New function. + * c.opt (-Wsizeof-pointer-memaccess): Add new option. + * c-opts.c (c_common_handle_option): Enable it for -Wall. + * c-common.h (sizeof_pointer_memaccess_warning): Add prototype. + * c-common.def (SIZEOF_EXPR): Moved here from cp-tree.def. + 2012-08-10 Richard Guenther <rguenther@suse.de> * c-pretty-print.c (pp_c_expression): Handle anonymous SSA names. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index ab3eb0a..502613a 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -1841,6 +1841,149 @@ strict_aliasing_warning (tree otype, tree type, tree expr) return false; } +/* Warn about memset (&a, 0, sizeof (&a)); and similar mistakes with + sizeof as last operand of certain builtins. */ + +void +sizeof_pointer_memaccess_warning (location_t loc, tree callee, + VEC(tree, gc) *params, tree sizeof_arg, + bool (*comp_types) (tree, tree)) +{ + tree type, dest = NULL_TREE, src = NULL_TREE, tem; + bool strop = false; + + if (TREE_CODE (callee) != FUNCTION_DECL + || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL + || sizeof_arg == error_mark_node + || VEC_length (tree, params) <= 1) + return; + + type = TYPE_P (sizeof_arg) ? sizeof_arg : TREE_TYPE (sizeof_arg); + if (!POINTER_TYPE_P (type)) + return; + + switch (DECL_FUNCTION_CODE (callee)) + { + case BUILT_IN_STRNCMP: + case BUILT_IN_STRNCASECMP: + case BUILT_IN_STRNCPY: + case BUILT_IN_STRNCAT: + strop = true; + /* FALLTHRU */ + case BUILT_IN_MEMCPY: + case BUILT_IN_MEMMOVE: + case BUILT_IN_MEMCMP: + if (VEC_length (tree, params) < 3) + return; + src = VEC_index (tree, params, 1); + dest = VEC_index (tree, params, 0); + break; + case BUILT_IN_MEMSET: + if (VEC_length (tree, params) < 3) + return; + dest = VEC_index (tree, params, 0); + break; + case BUILT_IN_STRNDUP: + src = VEC_index (tree, params, 0); + strop = true; + break; + default: + break; + } + + if (dest + && (tem = tree_strip_nop_conversions (dest)) + && POINTER_TYPE_P (TREE_TYPE (tem)) + && comp_types (TREE_TYPE (TREE_TYPE (tem)), type)) + return; + + if (src + && (tem = tree_strip_nop_conversions (src)) + && POINTER_TYPE_P (TREE_TYPE (tem)) + && comp_types (TREE_TYPE (TREE_TYPE (tem)), type)) + return; + + if (dest) + { + if (!TYPE_P (sizeof_arg) + && operand_equal_p (dest, sizeof_arg, 0) + && comp_types (TREE_TYPE (dest), type)) + { + if (TREE_CODE (sizeof_arg) == ADDR_EXPR && !strop) + warning_at (loc, OPT_Wsizeof_pointer_memaccess, + "argument to %<sizeof%> in %qD call is the same " + "expression as the destination; did you mean to " + "remove the addressof?", callee); + else if ((TYPE_PRECISION (TREE_TYPE (type)) + == TYPE_PRECISION (char_type_node)) + || strop) + warning_at (loc, OPT_Wsizeof_pointer_memaccess, + "argument to %<sizeof%> in %qD call is the same " + "expression as the destination; did you mean to " + "provide an explicit length?", callee); + else + warning_at (loc, OPT_Wsizeof_pointer_memaccess, + "argument to %<sizeof%> in %qD call is the same " + "expression as the destination; did you mean to " + "dereference it?", callee); + return; + } + + if (POINTER_TYPE_P (TREE_TYPE (dest)) + && !strop + && comp_types (TREE_TYPE (dest), type) + && !VOID_TYPE_P (TREE_TYPE (type))) + { + warning_at (loc, OPT_Wsizeof_pointer_memaccess, + "argument to %<sizeof%> in %qD call is the same " + "pointer type %qT as the destination; expected %qT " + "or an explicit length", callee, TREE_TYPE (dest), + TREE_TYPE (TREE_TYPE (dest))); + return; + } + } + + if (src) + { + if (!TYPE_P (sizeof_arg) + && operand_equal_p (src, sizeof_arg, 0) + && comp_types (TREE_TYPE (src), type)) + { + if (TREE_CODE (sizeof_arg) == ADDR_EXPR && !strop) + warning_at (loc, OPT_Wsizeof_pointer_memaccess, + "argument to %<sizeof%> in %qD call is the same " + "expression as the source; did you mean to " + "remove the addressof?", callee); + else if ((TYPE_PRECISION (TREE_TYPE (type)) + == TYPE_PRECISION (char_type_node)) + || strop) + warning_at (loc, OPT_Wsizeof_pointer_memaccess, + "argument to %<sizeof%> in %qD call is the same " + "expression as the source; did you mean to " + "provide an explicit length?", callee); + else + warning_at (loc, OPT_Wsizeof_pointer_memaccess, + "argument to %<sizeof%> in %qD call is the same " + "expression as the source; did you mean to " + "dereference it?", callee); + return; + } + + if (POINTER_TYPE_P (TREE_TYPE (src)) + && !strop + && comp_types (TREE_TYPE (src), type) + && !VOID_TYPE_P (TREE_TYPE (type))) + { + warning_at (loc, OPT_Wsizeof_pointer_memaccess, + "argument to %<sizeof%> in %qD call is the same " + "pointer type %qT as the source; expected %qT " + "or an explicit length", callee, TREE_TYPE (src), + TREE_TYPE (TREE_TYPE (src))); + return; + } + } +} + /* Warn for unlikely, improbable, or stupid DECL declarations of `main'. */ diff --git a/gcc/c-family/c-common.def b/gcc/c-family/c-common.def index 2a7df88..b6df9a3 100644 --- a/gcc/c-family/c-common.def +++ b/gcc/c-family/c-common.def @@ -2,7 +2,7 @@ additional tree codes used in the GNU C compiler (see tree.def for the standard codes). Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998, - 1999, 2000, 2001, 2004, 2005, 2007, 2009, 2010 + 1999, 2000, 2001, 2004, 2005, 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Written by Benjamin Chelf <chelf@codesourcery.com> @@ -53,6 +53,10 @@ DEFTREECODE (EXCESS_PRECISION_EXPR, "excess_precision_expr", tcc_expression, 1) number. */ DEFTREECODE (USERDEF_LITERAL, "userdef_literal", tcc_exceptional, 3) +/* Represents a 'sizeof' expression during C++ template expansion, + or for the purpose of -Wsizeof-pointer-memaccess warning. */ +DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", tcc_expression, 1) + /* Local variables: mode:c diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 050112e..9298e3d 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1,6 +1,6 @@ /* Definitions for c-common.c. - Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 + Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, + 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -768,6 +768,9 @@ extern tree fix_string_type (tree); extern void constant_expression_warning (tree); extern void constant_expression_error (tree); extern bool strict_aliasing_warning (tree, tree, tree); +extern void sizeof_pointer_memaccess_warning (location_t, tree, + VEC(tree, gc) *, tree, + bool (*) (tree, tree)); extern void warnings_for_convert_and_check (tree, tree, tree); extern tree convert_and_check (tree, tree); extern void overflow_warning (location_t, tree); diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 2fa59dc..29121b5 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -1,6 +1,6 @@ /* C/ObjC/C++ command line option handling. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, + 2012 Free Software Foundation, Inc. Contributed by Neil Booth. This file is part of GCC. @@ -374,6 +374,7 @@ c_common_handle_option (size_t scode, const char *arg, int value, warn_return_type = value; warn_sequence_point = value; /* Was C only. */ warn_switch = value; + warn_sizeof_pointer_memaccess = value; if (warn_strict_aliasing == -1) set_Wstrict_aliasing (&global_options, value); warn_address = value; diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 981b7ab..914d110 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -474,6 +474,9 @@ Wmissing-field-initializers C ObjC C++ ObjC++ Var(warn_missing_field_initializers) Warning EnabledBy(Wextra) Warn about missing fields in struct initializers +Wsizeof-pointer-memaccess +C ObjC C++ ObjC++ Var(warn_sizeof_pointer_memaccess) Warning + Wsuggest-attribute=format C ObjC C++ ObjC++ Var(warn_suggest_attribute_format) Warning Warn about functions which might be candidates for format attributes |