Commit 9f720c3e by Geoff Keating Committed by Geoffrey Keating

c-common.c (c_common_nodes_and_builtins): The first parameter to…

c-common.c (c_common_nodes_and_builtins): The first parameter to __builtin_va_start and __builtin_va_copy is now either a...

* c-common.c (c_common_nodes_and_builtins): The first parameter to
__builtin_va_start and __builtin_va_copy is now either a 'va_list'
or a reference to a va_list.
* builtins.c (stabilize_va_list): Simplify now we don't have to
work around C array address decay.
* c-typeck.c (convert_for_assignment): Handle assignment to
a reference parameter by taking the address of the RHS.
* ginclude/stdarg.h (va_start): Don't take address of first parameter.
(va_copy): Likewise.
(__va_copy): Likewise.
* ginclude/varargs.h (va_start): Likewise.
(__va_copy): Likewise.

From-SVN: r32821
parent abe79fd4
2000-03-29 Geoff Keating <geoffk@cygnus.com>
* c-common.c (c_common_nodes_and_builtins): The first parameter to
__builtin_va_start and __builtin_va_copy is now either a 'va_list'
or a reference to a va_list.
* builtins.c (stabilize_va_list): Simplify now we don't have to
work around C array address decay.
* c-typeck.c (convert_for_assignment): Handle assignment to
a reference parameter by taking the address of the RHS.
* ginclude/stdarg.h (va_start): Don't take address of first parameter.
(va_copy): Likewise.
(__va_copy): Likewise.
* ginclude/varargs.h (va_start): Likewise.
(__va_copy): Likewise.
Wed Mar 29 15:44:53 2000 Jeffrey A Law (law@cygnus.com) Wed Mar 29 15:44:53 2000 Jeffrey A Law (law@cygnus.com)
* stmt.c (stmt_loop_nest_empty): Fix thinko in last change. * stmt.c (stmt_loop_nest_empty): Fix thinko in last change.
......
...@@ -1901,66 +1901,43 @@ expand_builtin_next_arg (arglist) ...@@ -1901,66 +1901,43 @@ expand_builtin_next_arg (arglist)
from multiple evaluations. */ from multiple evaluations. */
static tree static tree
stabilize_va_list (valist, was_ptr) stabilize_va_list (valist, needs_lvalue)
tree valist; tree valist;
int was_ptr; int needs_lvalue;
{ {
if (TREE_CODE (va_list_type_node) == ARRAY_TYPE) if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
{ {
/* If stdarg.h took the address of an array-type valist that was passed if (TREE_SIDE_EFFECTS (valist))
as a parameter, we'll have taken the address of the parameter itself valist = save_expr (valist);
rather than the array as we'd intended. Undo this mistake. */
if (was_ptr)
{
STRIP_NOPS (valist);
/* Two cases: either &array, which decomposed to
<ptr <array <record> valist>>
or &ptr, which turned into
<ptr <ptr <record>>>
In the first case we'll need to put the ADDR_EXPR back
after frobbing the types as if &array[0]. */
if (TREE_CODE (valist) != ADDR_EXPR)
abort ();
valist = TREE_OPERAND (valist, 0);
}
if (TYPE_MAIN_VARIANT (TREE_TYPE (valist)) /* For this case, the backends will be expecting a pointer to
== TYPE_MAIN_VARIANT (va_list_type_node)) TREE_TYPE (va_list_type_node), but it's possible we've
{ actually been given an array (an actual va_list_type_node).
tree pt = build_pointer_type (TREE_TYPE (va_list_type_node)); So fix it. */
valist = build1 (ADDR_EXPR, pt, valist); if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
TREE_SIDE_EFFECTS (valist)
= TREE_SIDE_EFFECTS (TREE_OPERAND (valist, 0));
}
else
{ {
if (! POINTER_TYPE_P (TREE_TYPE (valist)) tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (valist))) tree p2 = build_pointer_type (va_list_type_node);
!= TYPE_MAIN_VARIANT (TREE_TYPE (va_list_type_node)))) valist = build1 (ADDR_EXPR, p2, valist);
abort (); valist = fold (build1 (NOP_EXPR, p1, valist));
} }
if (TREE_SIDE_EFFECTS (valist))
valist = save_expr (valist);
} }
else else
{ {
if (! was_ptr) tree pt;
{
tree pt;
if (! needs_lvalue)
{
if (! TREE_SIDE_EFFECTS (valist)) if (! TREE_SIDE_EFFECTS (valist))
return valist; return valist;
pt = build_pointer_type (va_list_type_node); pt = build_pointer_type (va_list_type_node);
valist = fold (build1 (ADDR_EXPR, pt, valist)); valist = fold (build1 (ADDR_EXPR, pt, valist));
TREE_SIDE_EFFECTS (valist) = 1; TREE_SIDE_EFFECTS (valist) = 1;
} }
if (TREE_SIDE_EFFECTS (valist)) if (TREE_SIDE_EFFECTS (valist))
valist = save_expr (valist); valist = save_expr (valist);
valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
valist)); valist));
} }
......
...@@ -3478,7 +3478,7 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins) ...@@ -3478,7 +3478,7 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins)
tree traditional_cptr_type_node; tree traditional_cptr_type_node;
tree traditional_len_type_node; tree traditional_len_type_node;
tree traditional_len_endlink; tree traditional_len_endlink;
tree va_list_ptr_type_node; tree va_list_ref_type_node;
tree va_list_arg_type_node; tree va_list_arg_type_node;
pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"), pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
...@@ -3490,13 +3490,17 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins) ...@@ -3490,13 +3490,17 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins)
pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"), pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"),
sizetype)); sizetype));
va_list_ptr_type_node = build_pointer_type (va_list_type_node);
if (TREE_CODE (va_list_type_node) == ARRAY_TYPE) if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
va_list_arg_type_node = build_pointer_type (TREE_TYPE (va_list_type_node)); {
va_list_arg_type_node = va_list_ref_type_node =
build_pointer_type (TREE_TYPE (va_list_type_node));
}
else else
va_list_arg_type_node = va_list_type_node; {
va_list_arg_type_node = va_list_type_node;
va_list_ref_type_node = build_reference_type (va_list_type_node);
}
endlink = void_list_node; endlink = void_list_node;
int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink); int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
double_endlink = tree_cons (NULL_TREE, double_type_node, endlink); double_endlink = tree_cons (NULL_TREE, double_type_node, endlink);
...@@ -3725,28 +3729,28 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins) ...@@ -3725,28 +3729,28 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins)
builtin_function ("__builtin_varargs_start", builtin_function ("__builtin_varargs_start",
build_function_type (void_type_node, build_function_type (void_type_node,
tree_cons (NULL_TREE, tree_cons (NULL_TREE,
va_list_ptr_type_node, va_list_ref_type_node,
endlink)), endlink)),
BUILT_IN_VARARGS_START, BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_VARARGS_START, BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("__builtin_stdarg_start", builtin_function ("__builtin_stdarg_start",
build_function_type (void_type_node, build_function_type (void_type_node,
tree_cons (NULL_TREE, tree_cons (NULL_TREE,
va_list_ptr_type_node, va_list_ref_type_node,
NULL_TREE)), NULL_TREE)),
BUILT_IN_STDARG_START, BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_STDARG_START, BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("__builtin_va_end", builtin_function ("__builtin_va_end",
build_function_type (void_type_node, build_function_type (void_type_node,
tree_cons (NULL_TREE, tree_cons (NULL_TREE,
va_list_arg_type_node, va_list_ref_type_node,
endlink)), endlink)),
BUILT_IN_VA_END, BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_VA_END, BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("__builtin_va_copy", builtin_function ("__builtin_va_copy",
build_function_type (void_type_node, build_function_type (void_type_node,
tree_cons (NULL_TREE, tree_cons (NULL_TREE,
va_list_ptr_type_node, va_list_ref_type_node,
tree_cons (NULL_TREE, tree_cons (NULL_TREE,
va_list_arg_type_node, va_list_arg_type_node,
endlink))), endlink))),
......
...@@ -3960,11 +3960,32 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum) ...@@ -3960,11 +3960,32 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
error ("void value not ignored as it ought to be"); error ("void value not ignored as it ought to be");
return error_mark_node; return error_mark_node;
} }
/* A type converts to a reference to it.
This code doesn't fully support references, it's just for the
special case of va_start and va_copy. */
if (codel == REFERENCE_TYPE
&& comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
{
if (mark_addressable (rhs) == 0)
return error_mark_node;
rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
/* We already know that these two types are compatible, but they
may not be exactly identical. In fact, `TREE_TYPE (type)' is
likely to be __builtin_va_list and `TREE_TYPE (rhs)' is
likely to be va_list, a typedef to __builtin_va_list, which
is different enough that it will cause problems later. */
if (TREE_TYPE (TREE_TYPE (rhs)) != TREE_TYPE (type))
rhs = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), rhs);
rhs = build1 (NOP_EXPR, type, rhs);
return rhs;
}
/* Arithmetic types all interconvert, and enum is treated like int. */ /* Arithmetic types all interconvert, and enum is treated like int. */
if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == ENUMERAL_TYPE else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
|| codel == COMPLEX_TYPE) || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE)
&& (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_TYPE && (coder == INTEGER_TYPE || coder == REAL_TYPE
|| coder == COMPLEX_TYPE)) || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE))
return convert_and_check (type, rhs); return convert_and_check (type, rhs);
/* Conversion to a transparent union from its member types. /* Conversion to a transparent union from its member types.
......
/* Copyright (C) 1989, 1997, 1998, 1999 Free Software Foundation, Inc. /* Copyright (C) 1989, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
...@@ -51,13 +51,13 @@ typedef __builtin_va_list __gnuc_va_list; ...@@ -51,13 +51,13 @@ typedef __builtin_va_list __gnuc_va_list;
actual type **after default promotions**. actual type **after default promotions**.
Thus, va_arg (..., short) is not valid. */ Thus, va_arg (..., short) is not valid. */
#define va_start(v,l) __builtin_stdarg_start(&(v),l) #define va_start(v,l) __builtin_stdarg_start((v),l)
#define va_end __builtin_va_end #define va_end __builtin_va_end
#define va_arg __builtin_va_arg #define va_arg __builtin_va_arg
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L #if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L
#define va_copy(d,s) __builtin_va_copy(&(d),(s)) #define va_copy(d,s) __builtin_va_copy((d),(s))
#endif #endif
#define __va_copy(d,s) __builtin_va_copy(&(d),(s)) #define __va_copy(d,s) __builtin_va_copy((d),(s))
/* Define va_list, if desired, from __gnuc_va_list. */ /* Define va_list, if desired, from __gnuc_va_list. */
......
/* Copyright (C) 1989, 1997, 1998, 1999 Free Software Foundation, Inc. /* Copyright (C) 1989, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
...@@ -63,10 +63,10 @@ typedef int __builtin_va_alist_t __attribute__((__mode__(__word__))); ...@@ -63,10 +63,10 @@ typedef int __builtin_va_alist_t __attribute__((__mode__(__word__)));
typedef __builtin_va_list __gnuc_va_list; typedef __builtin_va_list __gnuc_va_list;
#endif #endif
#define va_start(v) __builtin_varargs_start(&(v)) #define va_start(v) __builtin_varargs_start((v))
#define va_end __builtin_va_end #define va_end __builtin_va_end
#define va_arg __builtin_va_arg #define va_arg __builtin_va_arg
#define __va_copy(d,s) __builtin_va_copy(&(d),(s)) #define __va_copy(d,s) __builtin_va_copy((d),(s))
/* Define va_list from __gnuc_va_list. */ /* Define va_list from __gnuc_va_list. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment