summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpinskia <pinskia@138bc75d-0d04-0410-961f-82ee72b054a4>2004-12-04 14:11:45 +0000
committerpinskia <pinskia@138bc75d-0d04-0410-961f-82ee72b054a4>2004-12-04 14:11:45 +0000
commit743b0c6afc7593e469c1350e4d6ac62753275188 (patch)
treecbf7c78afc4e2cbb6aeed7f265db741b9c045876
parenta9b22d67e41dbf12d64eea7f33455a2da23cc43e (diff)
downloadgcc-743b0c6afc7593e469c1350e4d6ac62753275188.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@91727 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/builtins.c37
-rw-r--r--gcc/gimplify.c22
-rw-r--r--gcc/tree.h1
3 files changed, 48 insertions, 12 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 6c17e23acf9..7dbfb2099cb 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 6ee49b67f31..6a9e3b140c7 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 b9ce3acd965..a6963796c31 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);