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]

[PATCH]: PR c/21911 named parameter mistakenly identified as sentinel


This patch addresses PR c/21911, a failure to warn about a missing
sentinel when the sentinel appears in one of the named arguments of
the function call but not where it's supposed to appear in the
variable arguments.  This happens when too few variable arguments are
supplied and by chance the sentinel in the named arguments sits in the
right spot relative to the end.

Fixed by skipping past the named arguments before looking for the
sentinel.

I also updated the testcase accordingly.  Plus I noticed that the
execl* calls in the testcase were missing `arg0'.  Although the
testcase is never executed and passes a compile test, aesthetically I
couldn't resist fixing that too.

Okay for mainline?

		Thanks,
		--Kaveh


2005-06-05  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	PR c/21911
	* c-common.c (check_function_sentinel): Pass in named argument
	list, skip over named arguments before looking for a sentinel.
	(check_function_arguments): Pass in named argument list.
	* c-common.h (check_function_arguments): Likewise.
	* c-typeck.c (build_function_call): Likewise.

cp:
	* call.c (build_over_call): Pass in named argument list to
	`check_function_arguments'.
	* typeck.c (build_function_call): Likewise.

testsuite:
	PR c/21911
	* gcc.dg/format/sentinel-1.c: Update.  Fix execl* calls.

diff -rup orig/egcc-CVS20050605/gcc/c-common.c egcc-CVS20050605/gcc/c-common.c
--- orig/egcc-CVS20050605/gcc/c-common.c	2005-05-26 21:26:52.000000000 -0400
+++ egcc-CVS20050605/gcc/c-common.c	2005-06-06 14:26:14.000000000 -0400
@@ -5097,14 +5097,21 @@ check_function_nonnull (tree attrs, tree
    from the end) is a (pointer)0.  */
 
 static void
-check_function_sentinel (tree attrs, tree params)
+check_function_sentinel (tree attrs, tree params, tree typelist)
 {
   tree attr = lookup_attribute ("sentinel", attrs);
 
   if (attr)
     {
-      if (!params)
-	warning (0, "missing sentinel in function call");
+      /* Skip over the named arguments.  */
+      while (typelist && params)
+      {
+	typelist = TREE_CHAIN (typelist);
+	params = TREE_CHAIN (params);
+      }
+      
+      if (typelist || !params)
+	warning (0, "not enough variable arguments to fit a sentinel");
       else
         {
 	  tree sentinel, end;
@@ -5126,7 +5133,7 @@ check_function_sentinel (tree attrs, tre
 	    }
 	  if (pos > 0)
 	    {
-	      warning (0, "not enough arguments to fit a sentinel");
+	      warning (0, "not enough variable arguments to fit a sentinel");
 	      return;
 	    }
 
@@ -5340,7 +5347,7 @@ handle_sentinel_attribute (tree *node, t
 
 /* Check for valid arguments being passed to a function.  */
 void
-check_function_arguments (tree attrs, tree params)
+check_function_arguments (tree attrs, tree params, tree typelist)
 {
   /* Check for null being passed in a pointer argument that must be
      non-null.  We also need to do this if format checking is enabled.  */
@@ -5353,7 +5360,7 @@ check_function_arguments (tree attrs, tr
   if (warn_format)
     {
       check_function_format (attrs, params);
-      check_function_sentinel (attrs, params);
+      check_function_sentinel (attrs, params, typelist);
     }
 }
 
diff -rup orig/egcc-CVS20050605/gcc/c-common.h egcc-CVS20050605/gcc/c-common.h
--- orig/egcc-CVS20050605/gcc/c-common.h	2005-05-28 20:43:15.000000000 -0400
+++ egcc-CVS20050605/gcc/c-common.h	2005-06-06 14:25:58.000000000 -0400
@@ -626,7 +626,7 @@ extern void finish_fname_decls (void);
 extern const char *fname_as_string (int);
 extern tree fname_decl (unsigned, tree);
 
-extern void check_function_arguments (tree, tree);
+extern void check_function_arguments (tree, tree, tree);
 extern void check_function_arguments_recurse (void (*)
 					      (void *, tree,
 					       unsigned HOST_WIDE_INT),
diff -rup orig/egcc-CVS20050605/gcc/c-typeck.c egcc-CVS20050605/gcc/c-typeck.c
--- orig/egcc-CVS20050605/gcc/c-typeck.c	2005-06-03 21:46:41.000000000 -0400
+++ egcc-CVS20050605/gcc/c-typeck.c	2005-06-06 14:25:58.000000000 -0400
@@ -2076,7 +2076,8 @@ build_function_call (tree function, tree
 
   /* Check that the arguments to the function are valid.  */
 
-  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params);
+  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
+			    TYPE_ARG_TYPES (fntype));
 
   result = build3 (CALL_EXPR, TREE_TYPE (fntype),
 		   function, coerced_params, NULL_TREE);
diff -rup orig/egcc-CVS20050605/gcc/cp/call.c egcc-CVS20050605/gcc/cp/call.c
--- orig/egcc-CVS20050605/gcc/cp/call.c	2005-05-27 20:38:47.000000000 -0400
+++ egcc-CVS20050605/gcc/cp/call.c	2005-06-06 14:25:58.000000000 -0400
@@ -4790,7 +4790,7 @@ build_over_call (struct z_candidate *can
   converted_args = nreverse (converted_args);
 
   check_function_arguments (TYPE_ATTRIBUTES (TREE_TYPE (fn)),
-			    converted_args);
+			    converted_args, TYPE_ARG_TYPES (TREE_TYPE (fn)));
 
   /* Avoid actually calling copy constructors and copy assignment operators,
      if possible.  */
diff -rup orig/egcc-CVS20050605/gcc/cp/typeck.c egcc-CVS20050605/gcc/cp/typeck.c
--- orig/egcc-CVS20050605/gcc/cp/typeck.c	2005-06-03 21:46:43.000000000 -0400
+++ egcc-CVS20050605/gcc/cp/typeck.c	2005-06-06 14:25:58.000000000 -0400
@@ -2486,7 +2486,8 @@ build_function_call (tree function, tree
   /* Check for errors in format strings and inappropriately
      null parameters.  */
 
-  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params);
+  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
+			    TYPE_ARG_TYPES (fntype));
 
   return build_cxx_call (function, coerced_params);
 }
diff -rup orig/egcc-CVS20050605/gcc/testsuite/gcc.dg/format/sentinel-1.c egcc-CVS20050605/gcc/testsuite/gcc.dg/format/sentinel-1.c
--- orig/egcc-CVS20050605/gcc/testsuite/gcc.dg/format/sentinel-1.c	2004-09-04 22:55:28.000000000 -0400
+++ egcc-CVS20050605/gcc/testsuite/gcc.dg/format/sentinel-1.c	2005-06-06 14:26:41.000000000 -0400
@@ -27,40 +27,47 @@ extern void foo10 (const char *, ...) __
 
 extern void bar(void)
 {
-  foo1 (); /* { dg-error "missing sentinel|too few arguments" "sentinel" } */
-  foo1 ("a"); /* { dg-warning "missing sentinel" "sentinel" } */
+  foo1 (); /* { dg-error "not enough|too few arguments" "sentinel" } */
+  foo1 (NULL); /* { dg-warning "not enough" "sentinel" } */
+  foo1 ("a"); /* { dg-warning "not enough" "sentinel" } */
   foo1 ("a", 1); /* { dg-warning "missing sentinel" "sentinel" } */
   foo1 ("a", 0); /* { dg-warning "missing sentinel" "sentinel" } */
   foo1 ("a", (void*)1); /* { dg-warning "missing sentinel" "sentinel" } */
   foo1 ("a", NULL, 1); /* { dg-warning "missing sentinel" "sentinel" } */
   foo1 ("a", NULL);
 
+  foo5 (NULL); /* { dg-warning "not enough" "sentinel" } */
+  foo5 (NULL, 1); /* { dg-warning "not enough" "sentinel" } */
+  foo5 ("a", NULL); /* { dg-warning "not enough" "sentinel" } */
+  foo5 ("a", NULL, 1);
   foo5 ("a", 1, 2, 3, NULL); /* { dg-warning "missing sentinel" "sentinel" } */
   foo5 ("a", 1, 2, NULL, 3);
   foo5 ("a", 1, NULL, 2, 3); /* { dg-warning "missing sentinel" "sentinel" } */
   foo5 ("a", NULL, 1, 2, 3); /* { dg-warning "missing sentinel" "sentinel" } */
   foo5 ("a", 0, 1, 2, 3); /* { dg-warning "missing sentinel" "sentinel" } */
 
-  foo6 ("a", 1, NULL); /* { dg-warning "not enough arguments" "sentinel" } */
-  foo6 ("a", 1, NULL, 2); /* { dg-warning "not enough arguments" "sentinel" } */
-  foo6 ("a", 1, NULL, 2, 3); /* { dg-warning "not enough arguments" "sentinel" } */
-  foo6 ("a", NULL, 1, 2, 3); /* { dg-warning "not enough arguments" "sentinel" } */
-  foo6 ("a", NULL, 1, 2, 3, 4); /* { dg-warning "missing sentinel" "sentinel" } */
+  foo6 ("a", 1, NULL); /* { dg-warning "not enough" "sentinel" } */
+  foo6 ("a", 1, NULL, 2); /* { dg-warning "not enough" "sentinel" } */
+  foo6 ("a", 1, NULL, 2, 3); /* { dg-warning "not enough" "sentinel" } */
+  foo6 ("a", NULL, 1, 2, 3); /* { dg-warning "not enough" "sentinel" } */
+  foo6 ("a", NULL, 1, 2, 3, 4); /* { dg-warning "not enough" "sentinel" } */
+  foo6 (NULL, 1, 2, 3, 4, 5); /* { dg-warning "not enough" "sentinel" } */
   foo6 ("a", NULL, 1, 2, 3, 4, 5);
+  foo6 ("a", 0, NULL, 1, 2, 3, 4, 5);
   foo6 ("a", 0, 1, 2, 3, 4, 5); /* { dg-warning "missing sentinel" "sentinel" } */
   foo6 ("a", NULL, 1, 2, 3, 4, 5, 6); /* { dg-warning "missing sentinel" "sentinel" } */
 
   foo7 ("a", 1, 2, 3, NULL);
 
-  execl ("/bin/ls", "-aFC"); /* { dg-warning "missing sentinel" "sentinel" } */
-  execl ("/bin/ls", "-aFC", 0); /* { dg-warning "missing sentinel" "sentinel" } */
-  execl ("/bin/ls", "-aFC", NULL);
-
-  execlp ("ls", "-aFC"); /* { dg-warning "missing sentinel" "sentinel" } */
-  execlp ("ls", "-aFC", 0); /* { dg-warning "missing sentinel" "sentinel" } */
-  execlp ("ls", "-aFC", NULL);
-
-  execle ("ls", "-aFC", ".", envp); /* { dg-warning "missing sentinel" "sentinel" } */
-  execle ("ls", "-aFC", ".", 0, envp); /* { dg-warning "missing sentinel" "sentinel" } */
-  execle ("ls", "-aFC", ".", NULL, envp);
+  execl ("/bin/ls", "/bin/ls", "-aFC"); /* { dg-warning "missing sentinel" "sentinel" } */
+  execl ("/bin/ls", "/bin/ls", "-aFC", 0); /* { dg-warning "missing sentinel" "sentinel" } */
+  execl ("/bin/ls", "/bin/ls", "-aFC", NULL);
+
+  execlp ("ls", "ls", "-aFC"); /* { dg-warning "missing sentinel" "sentinel" } */
+  execlp ("ls", "ls", "-aFC", 0); /* { dg-warning "missing sentinel" "sentinel" } */
+  execlp ("ls", "ls", "-aFC", NULL);
+
+  execle ("ls", "ls", "-aFC", ".", envp); /* { dg-warning "missing sentinel" "sentinel" } */
+  execle ("ls", "ls", "-aFC", ".", 0, envp); /* { dg-warning "missing sentinel" "sentinel" } */
+  execle ("ls", "ls", "-aFC", ".", NULL, envp);
 }


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