From 2efcfa4ef6cd96146871e8c7f4de5ed76a9fefab Mon Sep 17 00:00:00 2001
From: Andrew Pinski <pinskia@gcc.gnu.org>
Date: Sat, 4 Dec 2004 06:11:45 -0800
Subject: [PATCH] re PR middle-end/17909 (ICE: verifiy_stms failed)

2004-12-04  Andrew  Pinski  <pinskia@physics.uc.edu>

        PR middle-end/17909
        * builtins.c (fold_builtin_next_arg): Export and return true
        when there is a warning or an error.
        (expand_builtin_va_start): When fold_builtin_next_arg returns true,
        return const0_rtx.
        (expand_builtin): Likewise.
        * gimplify.c (gimplify_call_expr): Error out if there is not
        enough arguments to va_start. Call fold_builtin_next_arg also
        on the second argument.
        * tree.h (fold_builtin_next_arg): Prototype.

From-SVN: r91727
---
 gcc/builtins.c | 37 ++++++++++++++++++++++++++++---------
 gcc/gimplify.c | 22 +++++++++++++++++++---
 gcc/tree.h     |  1 +
 3 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 6c17e23acf93..7dbfb2099cb7 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -185,7 +185,6 @@ static tree fold_builtin_strcat (tree);
 static tree fold_builtin_strncat (tree);
 static tree fold_builtin_strspn (tree);
 static tree fold_builtin_strcspn (tree);
-static void fold_builtin_next_arg (tree);
 static tree fold_builtin_sprintf (tree, int);
 
 
@@ -3868,7 +3867,10 @@ expand_builtin_va_start (tree arglist)
   if (TREE_CHAIN (chain))
     error ("too many arguments to function %<va_start%>");
 
-  fold_builtin_next_arg (chain);
+  if (fold_builtin_next_arg (chain))
+    {
+      return const0_rtx;
+    }
 
   nextarg = expand_builtin_next_arg (chain);
   valist = stabilize_va_list (TREE_VALUE (arglist), 1);
@@ -5249,7 +5251,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
 
       /* Return the address of the first anonymous stack arg.  */
     case BUILT_IN_NEXT_ARG:
-      fold_builtin_next_arg (arglist);
+      if (fold_builtin_next_arg (arglist))
+        return const0_rtx;
       return expand_builtin_next_arg (arglist);
 
     case BUILT_IN_CLASSIFY_TYPE:
@@ -8650,7 +8653,10 @@ fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len)
   return build_function_call_expr (fn, arglist);
 }
 
-static void
+/* Fold the new_arg's agruments (ARGLIST). Returns true if there was an error
+   produced.  False otherwise.  This is done so that we don't output the error
+   or warning twice or three times.  */
+bool
 fold_builtin_next_arg (tree arglist)
 {
   tree fntype = TREE_TYPE (current_function_decl);
@@ -8658,7 +8664,10 @@ fold_builtin_next_arg (tree arglist)
   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");
+    {
+      error ("%<va_start%> used in function with fixed args");
+      return true;
+    }
   else if (arglist)
     {
       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
@@ -8674,13 +8683,23 @@ fold_builtin_next_arg (tree arglist)
 	     || TREE_CODE (arg) == INDIRECT_REF)
 	arg = TREE_OPERAND (arg, 0);
       if (arg != last_parm)
-	warning ("second parameter of %<va_start%> not last named argument");
+        {
+	  /* FIXME: Sometimes with the tree optimizaters we can get the not the last argument
+	     even though the user used the last 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");
+    {
+      /* 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;
+    }
+  return false;
 }
 
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 6ee49b67f31f..6a9e3b140c7a 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1744,9 +1744,25 @@ gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
 	}
 
       if (DECL_FUNCTION_CODE (decl) == BUILT_IN_VA_START)
-	/* Avoid gimplifying the second argument to va_start, which needs
-	   to be the plain PARM_DECL.  */
-	return gimplify_arg (&TREE_VALUE (TREE_OPERAND (*expr_p, 1)), pre_p);
+        {
+	  tree arglist = TREE_OPERAND (*expr_p, 1);
+	  
+	  if (!arglist || !TREE_CHAIN (arglist))
+	    {
+	      error ("too few arguments to function %<va_start%>");
+	      *expr_p = build_empty_stmt ();
+	      return GS_OK;
+	    }
+	  
+	  if (fold_builtin_next_arg (TREE_CHAIN (arglist)))
+	    {
+	      *expr_p = build_empty_stmt ();
+	      return GS_OK;
+	    }
+	  /* Avoid gimplifying the second argument to va_start, which needs
+	     to be the plain PARM_DECL.  */
+	  return gimplify_arg (&TREE_VALUE (TREE_OPERAND (*expr_p, 1)), pre_p);
+	}
     }
 
   /* There is a sequence point before the call, so any side effects in
diff --git a/gcc/tree.h b/gcc/tree.h
index b9ce3acd965e..a6963796c312 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3535,6 +3535,7 @@ extern tree fold_builtin (tree, bool);
 extern tree fold_builtin_fputs (tree, bool, bool, tree);
 extern tree fold_builtin_strcpy (tree, tree);
 extern tree fold_builtin_strncpy (tree, tree);
+extern bool fold_builtin_next_arg (tree);
 extern enum built_in_function builtin_mathfn_code (tree);
 extern tree build_function_call_expr (tree, tree);
 extern tree mathfn_built_in (tree, enum built_in_function fn);
-- 
GitLab