From 9f720c3eba745cb4c97bd827c82f9c28bcbd0027 Mon Sep 17 00:00:00 2001 From: Geoff Keating Date: Thu, 30 Mar 2000 00:03:14 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 15 ++++++++++++ gcc/builtins.c | 63 ++++++++++++++++---------------------------------- gcc/c-common.c | 24 +++++++++++-------- gcc/c-typeck.c | 29 +++++++++++++++++++---- gcc/ginclude/stdarg.h | 8 +++---- gcc/ginclude/varargs.h | 6 ++--- 6 files changed, 81 insertions(+), 64 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fa6a801..8db409e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2000-03-29 Geoff Keating + + * 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) * stmt.c (stmt_loop_nest_empty): Fix thinko in last change. diff --git a/gcc/builtins.c b/gcc/builtins.c index 0271d12..94997fb 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1901,66 +1901,43 @@ expand_builtin_next_arg (arglist) from multiple evaluations. */ static tree -stabilize_va_list (valist, was_ptr) +stabilize_va_list (valist, needs_lvalue) tree valist; - int was_ptr; + int needs_lvalue; { if (TREE_CODE (va_list_type_node) == ARRAY_TYPE) { - /* If stdarg.h took the address of an array-type valist that was passed - as a parameter, we'll have taken the address of the parameter itself - rather than the array as we'd intended. Undo this mistake. */ - - if (was_ptr) - { - STRIP_NOPS (valist); - - /* Two cases: either &array, which decomposed to - valist>> - or &ptr, which turned into - >> - 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 (TREE_SIDE_EFFECTS (valist)) + valist = save_expr (valist); - if (TYPE_MAIN_VARIANT (TREE_TYPE (valist)) - == TYPE_MAIN_VARIANT (va_list_type_node)) - { - tree pt = build_pointer_type (TREE_TYPE (va_list_type_node)); - valist = build1 (ADDR_EXPR, pt, valist); - TREE_SIDE_EFFECTS (valist) - = TREE_SIDE_EFFECTS (TREE_OPERAND (valist, 0)); - } - else + /* For this case, the backends will be expecting a pointer to + TREE_TYPE (va_list_type_node), but it's possible we've + actually been given an array (an actual va_list_type_node). + So fix it. */ + if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) { - if (! POINTER_TYPE_P (TREE_TYPE (valist)) - || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (valist))) - != TYPE_MAIN_VARIANT (TREE_TYPE (va_list_type_node)))) - abort (); + tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node)); + tree p2 = build_pointer_type (va_list_type_node); + valist = build1 (ADDR_EXPR, p2, valist); + valist = fold (build1 (NOP_EXPR, p1, valist)); } - - if (TREE_SIDE_EFFECTS (valist)) - valist = save_expr (valist); } else { - if (! was_ptr) - { - tree pt; + tree pt; + if (! needs_lvalue) + { if (! TREE_SIDE_EFFECTS (valist)) return valist; - + 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; } + if (TREE_SIDE_EFFECTS (valist)) - valist = save_expr (valist); + valist = save_expr (valist); valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist)); } diff --git a/gcc/c-common.c b/gcc/c-common.c index 0589c03..97aba25 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -3478,7 +3478,7 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins) tree traditional_cptr_type_node; tree traditional_len_type_node; tree traditional_len_endlink; - tree va_list_ptr_type_node; + tree va_list_ref_type_node; tree va_list_arg_type_node; 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) pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"), sizetype)); - va_list_ptr_type_node = build_pointer_type (va_list_type_node); - 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 - 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; int_endlink = tree_cons (NULL_TREE, integer_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) builtin_function ("__builtin_varargs_start", build_function_type (void_type_node, tree_cons (NULL_TREE, - va_list_ptr_type_node, + va_list_ref_type_node, endlink)), BUILT_IN_VARARGS_START, BUILT_IN_NORMAL, NULL_PTR); builtin_function ("__builtin_stdarg_start", build_function_type (void_type_node, tree_cons (NULL_TREE, - va_list_ptr_type_node, + va_list_ref_type_node, NULL_TREE)), BUILT_IN_STDARG_START, BUILT_IN_NORMAL, NULL_PTR); builtin_function ("__builtin_va_end", build_function_type (void_type_node, tree_cons (NULL_TREE, - va_list_arg_type_node, + va_list_ref_type_node, endlink)), BUILT_IN_VA_END, BUILT_IN_NORMAL, NULL_PTR); builtin_function ("__builtin_va_copy", build_function_type (void_type_node, tree_cons (NULL_TREE, - va_list_ptr_type_node, + va_list_ref_type_node, tree_cons (NULL_TREE, va_list_arg_type_node, endlink))), diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 21a9557..f66d1b9 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -3960,11 +3960,32 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum) error ("void value not ignored as it ought to be"); 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. */ - if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == ENUMERAL_TYPE - || codel == COMPLEX_TYPE) - && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_TYPE - || coder == COMPLEX_TYPE)) + else if ((codel == INTEGER_TYPE || codel == REAL_TYPE + || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE) + && (coder == INTEGER_TYPE || coder == REAL_TYPE + || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE)) return convert_and_check (type, rhs); /* Conversion to a transparent union from its member types. diff --git a/gcc/ginclude/stdarg.h b/gcc/ginclude/stdarg.h index 3337065..9f6215d 100644 --- a/gcc/ginclude/stdarg.h +++ b/gcc/ginclude/stdarg.h @@ -1,4 +1,4 @@ -/* 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. @@ -51,13 +51,13 @@ typedef __builtin_va_list __gnuc_va_list; actual type **after default promotions**. 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_arg __builtin_va_arg #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 -#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. */ diff --git a/gcc/ginclude/varargs.h b/gcc/ginclude/varargs.h index 210b967..098094c 100644 --- a/gcc/ginclude/varargs.h +++ b/gcc/ginclude/varargs.h @@ -1,4 +1,4 @@ -/* 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. @@ -63,10 +63,10 @@ typedef int __builtin_va_alist_t __attribute__((__mode__(__word__))); typedef __builtin_va_list __gnuc_va_list; #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_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. */ -- 2.7.4