summaryrefslogtreecommitdiff
path: root/gcc/builtins.c
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 /gcc/builtins.c
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
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c37
1 files changed, 28 insertions, 9 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;
}