re PR tree-optimization/18828 (Extraneous warning with var_start and optimization)
authorJakub Jelinek <jakub@redhat.com>
Fri, 7 Jan 2005 09:01:00 +0000 (10:01 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 7 Jan 2005 09:01:00 +0000 (10:01 +0100)
PR tree-optimization/18828
* builtins.c (expand_builtin_next_arg): Remove argument and all
the argument checking.
(expand_builtin): Adjust caller.
(expand_builtin_va_start): Likewise.  Remove error for too many
arguments.
(fold_builtin_next_arg): Issue error for too many arguments.
After checking arguments, replace them with magic arguments that
prevent further checking of the args.

* gcc.dg/20050105-2.c: New test.

From-SVN: r93040

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/20050105-2.c [new file with mode: 0644]

index d9d38a691343db70481f875c6ecc26d3e3df2c8f..47923a1d95e4a51639bd08b32913567270a394f3 100644 (file)
@@ -1,3 +1,15 @@
+2005-01-07  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/18828
+       * builtins.c (expand_builtin_next_arg): Remove argument and all
+       the argument checking.
+       (expand_builtin): Adjust caller.
+       (expand_builtin_va_start): Likewise.  Remove error for too many
+       arguments.
+       (fold_builtin_next_arg): Issue error for too many arguments.
+       After checking arguments, replace them with magic arguments that
+       prevent further checking of the args.
+
 2005-01-06  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        * pa64-hpux.h (STARTFILE_SPEC): Fix typo in spec.
index a6a80cfa31377a672a86f66048a63b5fb0a0928e..b41212ae2e0f113d8bd9d8e4e0cdbcfe28db368b 100644 (file)
@@ -99,7 +99,7 @@ static rtx expand_builtin_mathfn (tree, rtx, rtx);
 static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
 static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
 static rtx expand_builtin_args_info (tree);
-static rtx expand_builtin_next_arg (tree);
+static rtx expand_builtin_next_arg (void);
 static rtx expand_builtin_va_start (tree);
 static rtx expand_builtin_va_end (tree);
 static rtx expand_builtin_va_copy (tree);
@@ -3743,43 +3743,13 @@ expand_builtin_args_info (tree arglist)
   return const0_rtx;
 }
 
-/* Expand ARGLIST, from a call to __builtin_next_arg.  */
+/* Expand a call to __builtin_next_arg.  */
 
 static rtx
-expand_builtin_next_arg (tree arglist)
+expand_builtin_next_arg (void)
 {
-  tree fntype = TREE_TYPE (current_function_decl);
-
-  if (TYPE_ARG_TYPES (fntype) == 0
-      || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
-         == void_type_node))
-    {
-      error ("%<va_start%> used in function with fixed args");
-      return const0_rtx;
-    }
-
-  if (arglist)
-    {
-      tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
-      tree arg = TREE_VALUE (arglist);
-
-      /* Strip off all nops for the sake of the comparison.  This
-        is not quite the same as STRIP_NOPS.  It does more.
-        We must also strip off INDIRECT_EXPR for C++ reference
-        parameters.  */
-      while (TREE_CODE (arg) == NOP_EXPR
-            || TREE_CODE (arg) == CONVERT_EXPR
-            || TREE_CODE (arg) == NON_LVALUE_EXPR
-            || TREE_CODE (arg) == INDIRECT_REF)
-       arg = TREE_OPERAND (arg, 0);
-      if (arg != last_parm)
-       warning ("second parameter of %<va_start%> not last named argument");
-    }
-  else
-    /* Evidently an out of date version of <stdarg.h>; can't validate
-       va_start's second argument, but can still work as intended.  */
-    warning ("%<__builtin_next_arg%> called without an argument");
-
+  /* Checking arguments is already done in fold_builtin_next_arg
+     that must be called before this function.  */
   return expand_binop (Pmode, add_optab,
                       current_function_internal_arg_pointer,
                       current_function_arg_offset_rtx,
@@ -3867,15 +3837,11 @@ expand_builtin_va_start (tree arglist)
       error ("too few arguments to function %<va_start%>");
       return const0_rtx;
     }
-  if (TREE_CHAIN (chain))
-    error ("too many arguments to function %<va_start%>");
 
   if (fold_builtin_next_arg (chain))
-    {
-      return const0_rtx;
-    }
+    return const0_rtx;
 
-  nextarg = expand_builtin_next_arg (chain);
+  nextarg = expand_builtin_next_arg ();
   valist = stabilize_va_list (TREE_VALUE (arglist), 1);
 
 #ifdef EXPAND_BUILTIN_VA_START
@@ -5256,7 +5222,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     case BUILT_IN_NEXT_ARG:
       if (fold_builtin_next_arg (arglist))
         return const0_rtx;
-      return expand_builtin_next_arg (arglist);
+      return expand_builtin_next_arg ();
 
     case BUILT_IN_CLASSIFY_TYPE:
       return expand_builtin_classify_type (arglist);
@@ -8671,11 +8637,29 @@ fold_builtin_next_arg (tree arglist)
       error ("%<va_start%> used in function with fixed args");
       return true;
     }
-  else if (arglist)
+  else if (!arglist)
+    {
+      /* Evidently an out of date version of <stdarg.h>; can't validate
+        va_start's second argument, but can still work as intended.  */
+      warning ("%<__builtin_next_arg%> called without an argument");
+      return true;
+    }
+  /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
+     when we checked the arguments and if needed issued a warning.  */
+  else if (!TREE_CHAIN (arglist)
+           || !integer_zerop (TREE_VALUE (arglist))
+           || !integer_zerop (TREE_VALUE (TREE_CHAIN (arglist)))
+           || TREE_CHAIN (TREE_CHAIN (arglist)))
     {
       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
       tree arg = TREE_VALUE (arglist);
 
+      if (TREE_CHAIN (arglist))
+        {
+          error ("%<va_start%> used with too many arguments");
+          return true;
+        }
+
       /* Strip off all nops for the sake of the comparison.  This
         is not quite the same as STRIP_NOPS.  It does more.
         We must also strip off INDIRECT_EXPR for C++ reference
@@ -8692,17 +8676,15 @@ fold_builtin_next_arg (tree arglist)
             argument.  We just warn and set the arg to be the last
             argument so that we will get wrong-code because of
             it.  */
-         arg = last_parm;
          warning ("second parameter of %<va_start%> not last named argument");
        }
-      TREE_VALUE (arglist) = arg;
-    }
-  else
-    {
-      /* Evidently an out of date version of <stdarg.h>; can't validate
-        va_start's second argument, but can still work as intended.  */
-      warning ("%<__builtin_next_arg%> called without an argument");
-      return true;
+      /* We want to verify the second parameter just once before the tree
+         optimizers are run and then avoid keeping it in the tree,
+         as otherwise we could warn even for correct code like:
+         void foo (int i, ...)
+         { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
+      TREE_VALUE (arglist) = integer_zero_node;
+      TREE_CHAIN (arglist) = build_tree_list (NULL, integer_zero_node);
     }
   return false;
 }
index b4a0f099cc3195fa1a97ae275222a7295194ab22..e12f5389ac8c3daa5c7969801f0ed1c44d082e56 100644 (file)
@@ -1,3 +1,8 @@
+2005-01-07  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/18828
+       * gcc.dg/20050105-2.c: New test.
+
 2005-01-07  Andreas Jaeger  <aj@suse.de>
 
        * gcc.dg/i386-local.c: Handle -m32/-m64 runs correctly.
diff --git a/gcc/testsuite/gcc.dg/20050105-2.c b/gcc/testsuite/gcc.dg/20050105-2.c
new file mode 100644 (file)
index 0000000..02ac159
--- /dev/null
@@ -0,0 +1,32 @@
+/* PR tree-optimization/18828 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+
+extern void abort (void);
+
+void foo (int x, ...)
+{
+  va_list ap;
+  if (x != 21)
+    abort ();
+  va_start (ap, x);
+  va_end (ap);
+}
+
+void bar (int x, ...)
+{
+  va_list ap;
+  x++;
+  va_start (ap, x);
+  va_end (ap);
+}
+
+void baz (int x, ...)
+{
+  va_list ap;
+  x = 0;
+  va_start (ap, x);
+  va_end (ap);
+}