diff options
author | pinskia <pinskia@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-12-04 14:11:45 +0000 |
---|---|---|
committer | pinskia <pinskia@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-12-04 14:11:45 +0000 |
commit | 743b0c6afc7593e469c1350e4d6ac62753275188 (patch) | |
tree | cbf7c78afc4e2cbb6aeed7f265db741b9c045876 | |
parent | a9b22d67e41dbf12d64eea7f33455a2da23cc43e (diff) | |
download | gcc-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.c | 37 | ||||
-rw-r--r-- | gcc/gimplify.c | 22 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
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); |