This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH: warn on memset with constant length 0


"Manuel López-Ibáñez" <lopezibanez@gmail.com> writes:
> On 15 Dec 2006 08:39:48 -0500, Assar <assar@kth.se> wrote:
> 
> When creating the patch, you should use the -p option of diff, please.
> It helps a lot when reviewing the patch.

I was not able to get my version of svn to send that to diff - I will
need to investigate more why that's the case.

> I am not a maintainer and I cannot approve your patch but I hope you
> find the following comments useful.

Thanks for your feedback.

> > Index: gcc/testsuite/gcc.dg/memset-constant0-3.c
> > ===================================================================
> > --- gcc/testsuite/gcc.dg/memset-constant0-3.c   (revision 0)
> > +++ gcc/testsuite/gcc.dg/memset-constant0-3.c   (revision 0)
> > @@ -0,0 +1,15 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-Wextra -O3" } */
> > +
> 
> Why use Wextra here? Is not Wmemset enabled by Wall ? Nevertheless, I
> think that the appropriate is to use Wmemset directly or even -Wextra
> -Wall -Wmemset all together.

Yeah, I think it should just be -Wmemset.  See patch below.

> Index: gcc/c.opt
> > +Wmemset
> > +C objC C++ ObjC++
> > +Warn about possible bad uses of \"memset\"
> > +
> 
> Why don't you use this instead ?
> 
> Wmemset
> C ObjC C++ ObjC++ Var(warn_memset) Init(-1)
> Warn about possible bad uses of \"memset\"

That makes perfect sense (without the Init(-1) - as you were
suggesting in your second mail).

> With the above changes, I think that the following are unnecessary:

Yeah.

> >  /* Warn about using __null (as NULL in C++) as sentinel.  For code compiled
> >     with GCC this doesn't matter as __null is guaranteed to have the right
> >     size.  */
> > @@ -5827,6 +5831,30 @@
> >    return NULL_TREE;
> >  }
> >
> > +/* Check arguments passed to memset.  */
> > +static void
> > +check_function_memset (tree params)
> > +{
> > +  tree param;
> > +  int param_num;
> > +
> > +  for (param = params, param_num = 1;
> > +       param;
> > +       param_num++, param = TREE_CHAIN (param))
> > +    if (param_num == 3 && integer_zerop (TREE_VALUE (param)))
> > +      warning (OPT_Wextra, "memset called with a constant 0 length");
> > +}
> > +
> 
> You have to use OPT_Wmemset instead of OPT_Wextra.

Good catch.

> Apart from that, is there no way to access the third argument
> directly? That "for" gives me the creeps.

I didn't find any other good examples in the code around there.

A patch with your suggestions incorporated is below.

/assar

gcc/ChangeLog

2006-12-15  Assar  <assar@permabit.com>

	* c-common.h: Add check_builtin_arguments prototype.
	* c-opts.c: Set -Wmemset in -Wall.
	
	* c-common.c: Add check for calling memset with constant third
	argument of 0.

	* c-typeck.c (build_function_call): Call check_builtin_arguments
	to get warnings.

	* c.opt: Add -Wmemset.

	* doc/invoke.texi: Document -Wmemset.

gcc/testsuite/ChangeLog

2006-12-15  Assar Westerlund  <assar@kth.se>

	* gcc.dg/memset-constant0-1.c: Test for "memset with 0" warning.
	* gcc.dg/memset-constant0-2.c: Likewise.
	* gcc.dg/memset-constant0-3.c: Test for not getting "memset with
	0" warning.

gcc/cp/ChangeLog

2006-12-15  Assar  <assar@permabit.com>

	* typeck.c (build_function_call): Call check_builtin_arguments to
	get warnings.
	* call.c (build_over_call): Same.

Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 119393)
+++ gcc/doc/invoke.texi	(working copy)
@@ -234,7 +234,7 @@
 -Wno-int-to-pointer-cast @gol
 -Wno-invalid-offsetof  -Winvalid-pch @gol
 -Wlarger-than-@var{len}  -Wunsafe-loop-optimizations  -Wlong-long @gol
--Wmain  -Wmissing-braces  -Wmissing-field-initializers @gol
+-Wmain  -Wmemset  -Wmissing-braces  -Wmissing-field-initializers @gol
 -Wmissing-format-attribute  -Wmissing-include-dirs @gol
 -Wmissing-noreturn @gol
 -Wno-multichar  -Wnonnull  -Wno-overflow @gol
@@ -2507,6 +2507,12 @@
 arguments, two, or three arguments of appropriate types.
 This warning is enabled by @option{-Wall}.
 
+@item -Wmemset
+@opindex -Wmemset
+Warn if the third argument to @samp{memset} is a constant 0.  This is
+usually caused by swapping arguments two and three.
+This warning is enabled by @option{-Wall}.
+
 @item -Wmissing-braces
 @opindex Wmissing-braces
 Warn if an aggregate or union initializer is not fully bracketed.  In
Index: gcc/testsuite/gcc.dg/memset-constant0-2.c
===================================================================
--- gcc/testsuite/gcc.dg/memset-constant0-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/memset-constant0-2.c	(revision 0)
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Wmemset" } */
+
+typedef unsigned size_t;
+void *memset(void *s, int c, size_t n);
+
+void clear(void *p, size_t len)
+{
+  memset(p, len, 0); /* { dg-warning "memset called with a constant 0 length" } */
+}
Index: gcc/testsuite/gcc.dg/memset-constant0-1.c
===================================================================
--- gcc/testsuite/gcc.dg/memset-constant0-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/memset-constant0-1.c	(revision 0)
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-Wmemset" } */
+
+typedef unsigned size_t;
+void *memset(void *s, int c, size_t n);
+
+int main()
+{
+  int foo;
+  memset(&foo, sizeof(foo), 0); /* { dg-warning "memset called with a constant 0 length" } */
+  return foo;
+}
Index: gcc/testsuite/gcc.dg/memset-constant0-3.c
===================================================================
--- gcc/testsuite/gcc.dg/memset-constant0-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/memset-constant0-3.c	(revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-Wmemset -O3" } */
+
+typedef unsigned size_t;
+void *memset(void *s, int c, size_t n);
+
+static inline void f(int *a, int size)
+{
+  memset(a, 0, size);
+}
+
+void g(void)
+{
+  f(0, 0);
+}
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 119393)
+++ gcc/cp/typeck.c	(working copy)
@@ -2691,6 +2691,8 @@
   check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
 			    TYPE_ARG_TYPES (fntype));
 
+  check_builtin_arguments (fndecl, coerced_params);
+
   return build_cxx_call (function, coerced_params);
 }
 
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 119393)
+++ gcc/cp/call.c	(working copy)
@@ -4889,6 +4889,8 @@
   check_function_arguments (TYPE_ATTRIBUTES (TREE_TYPE (fn)),
 			    converted_args, TYPE_ARG_TYPES (TREE_TYPE (fn)));
 
+  check_builtin_arguments (fn, converted_args);
+
   /* Avoid actually calling copy constructors and copy assignment operators,
      if possible.  */
 
Index: gcc/c.opt
===================================================================
--- gcc/c.opt	(revision 119393)
+++ gcc/c.opt	(working copy)
@@ -255,6 +255,10 @@
 C ObjC
 Warn about suspicious declarations of \"main\"
 
+Wmemset
+C ObjC C++ ObjC++ Var(warn_memset)
+Warn about possible bad uses of \"memset\"
+
 Wmissing-braces
 C ObjC C++ ObjC++ Var(warn_missing_braces)
 Warn about possibly missing braces around initializers
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 119393)
+++ gcc/c-typeck.c	(working copy)
@@ -2328,6 +2328,8 @@
   check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
 			    TYPE_ARG_TYPES (fntype));
 
+  check_builtin_arguments (fundecl, coerced_params);
+
   if (require_constant_value)
     {
       result = fold_build3_initializer (CALL_EXPR, TREE_TYPE (fntype),
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c	(revision 119393)
+++ gcc/c-opts.c	(working copy)
@@ -385,6 +385,7 @@
       set_Wunused (value);
       set_Wformat (value);
       set_Wimplicit (value);
+      warn_memset = value;
       warn_char_subscripts = value;
       warn_missing_braces = value;
       warn_parentheses = value;
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 119393)
+++ gcc/c-common.c	(working copy)
@@ -5827,6 +5827,30 @@
   return NULL_TREE;
 }
 
+/* Check arguments passed to memset.  */
+static void
+check_function_memset (tree params)
+{
+  tree param;
+  int param_num;
+
+  for (param = params, param_num = 1;
+       param;
+       param_num++, param = TREE_CHAIN (param))
+    if (param_num == 3 && integer_zerop (TREE_VALUE (param)))
+      warning (OPT_Wmemset, "memset called with a constant 0 length");
+}
+
+void
+check_builtin_arguments (tree fundecl, tree params)
+{
+  if (!fundecl || !DECL_BUILT_IN(fundecl))
+    return;
+
+  if (warn_memset && DECL_FUNCTION_CODE(fundecl) == BUILT_IN_MEMSET)
+    check_function_memset (params);
+}
+
 /* Check for valid arguments being passed to a function.  */
 void
 check_function_arguments (tree attrs, tree params, tree typelist)
Index: gcc/c-common.h
===================================================================
--- gcc/c-common.h	(revision 119393)
+++ gcc/c-common.h	(working copy)
@@ -634,6 +634,7 @@
 extern const char *fname_as_string (int);
 extern tree fname_decl (unsigned, tree);
 
+extern void check_builtin_arguments (tree, tree);
 extern void check_function_arguments (tree, tree, tree);
 extern void check_function_arguments_recurse (void (*)
 					      (void *, tree,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]