From c530479e15d804667c83dfb738ce9cae035de9f2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 7 Sep 1999 21:51:16 -0700 Subject: [PATCH] c-typeck.c (type_lists_compatible_p): Use simple_type_promotes_to. * c-typeck.c (type_lists_compatible_p): Use simple_type_promotes_to. (self_promoting_type_p): Delete. (self_promoting_args_p): Move ... * c-common.c: ... here. (c_common_nodes_and_builtins): Initialize lang_type_promotes_to. (simple_type_promotes_to): New. * builtins.c (lang_type_promotes_to): New. (expand_builtin_va_arg): Use it to give diagnostic for illegal types. * c-tree.h (C_PROMOTING_INTEGER_TYPE_P): Move ... * c-common.h: ... here. (self_promoting_args_p, simple_type_promotes_to): Declare. * c-decl.c (duplicate_decls): Use simple_type_promotes_to. (grokdeclarator): Likewise. * tree.h (lang_type_promotes_to): Declare. * cp-tree.h (C_PROMOTING_INTEGER_TYPE_P): Delete. * typeck.c (self_promoting_args_p): Delete. * gcc.dg/va-arg-1.c: New. From-SVN: r29180 --- gcc/ChangeLog | 17 ++++++++++ gcc/builtins.c | 36 +++++++++++++++++++- gcc/c-common.c | 58 +++++++++++++++++++++++++++++++++ gcc/c-common.h | 14 ++++++++ gcc/c-decl.c | 28 +++++----------- gcc/c-tree.h | 12 ------- gcc/c-typeck.c | 47 ++------------------------ gcc/cp/ChangeLog | 5 +++ gcc/cp/cp-tree.h | 12 ------- gcc/cp/typeck.c | 27 --------------- gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.dg/va-arg-1.c | 13 ++++++++ gcc/tree.h | 6 ++++ 13 files changed, 163 insertions(+), 116 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/va-arg-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f1425e91780..5770cfdb5ed 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +Tue Sep 7 21:41:38 1999 Richard Henderson + + * c-typeck.c (type_lists_compatible_p): Use simple_type_promotes_to. + (self_promoting_type_p): Delete. + (self_promoting_args_p): Move ... + * c-common.c: ... here. + (c_common_nodes_and_builtins): Initialize lang_type_promotes_to. + (simple_type_promotes_to): New. + * builtins.c (lang_type_promotes_to): New. + (expand_builtin_va_arg): Use it to give diagnostic for illegal types. + * c-tree.h (C_PROMOTING_INTEGER_TYPE_P): Move ... + * c-common.h: ... here. + (self_promoting_args_p, simple_type_promotes_to): Declare. + * c-decl.c (duplicate_decls): Use simple_type_promotes_to. + (grokdeclarator): Likewise. + * tree.h (lang_type_promotes_to): Declare. + Tue Sep 7 17:15:21 1999 Mark Mitchell Add some machine-dependent GC roots. diff --git a/gcc/builtins.c b/gcc/builtins.c index c4e36059d07..ebd7b12abd8 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -52,6 +52,8 @@ Boston, MA 02111-1307, USA. */ #define OUTGOING_REGNO(IN) (IN) #endif +tree (*lang_type_promotes_to) PROTO((tree)); + static int get_pointer_alignment PROTO((tree, unsigned)); static tree c_strlen PROTO((tree)); static rtx get_memory_rtx PROTO((tree)); @@ -1972,11 +1974,43 @@ expand_builtin_va_arg (valist, type) tree valist, type; { rtx addr, result; + tree promoted_type; if (TYPE_MAIN_VARIANT (TREE_TYPE (valist)) != TYPE_MAIN_VARIANT (va_list_type_node)) { - error ("first argument to `__builtin_va_arg' not of type `va_list'"); + error ("first argument to `va_arg' not of type `va_list'"); + addr = const0_rtx; + } + else if ((promoted_type = (*lang_type_promotes_to) (type)) != NULL_TREE) + { + const char *name = "", *pname; + static int gave_help; + + if (TYPE_NAME (type)) + { + if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) + name = IDENTIFIER_POINTER (TYPE_NAME (type)); + else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (type))) + name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); + } + if (TYPE_NAME (promoted_type)) + { + if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE) + pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type)); + else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (promoted_type))) + pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type))); + } + + error ("`%s' is promoted to `%s' when passed through `...'", name, pname); + if (! gave_help) + { + gave_help = 1; + error ("(so you should pass `%s' not `%s' to `va_arg')", pname, name); + } + addr = const0_rtx; } else diff --git a/gcc/c-common.c b/gcc/c-common.c index 4fea4ac70ae..3de1e9265a1 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -3804,6 +3804,10 @@ c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins) builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, NULL_PTR); #endif + + /* ??? Perhaps there's a better place to do this. But it is related + to __builtin_va_arg, so it isn't that off-the-wall. */ + lang_type_promotes_to = simple_type_promotes_to; } tree @@ -3967,4 +3971,58 @@ initializer_constant_valid_p (value, endtype) return 0; } + +/* Given a type, apply default promotions wrt unnamed function arguments + and return the new type. Return NULL_TREE if no change. */ +/* ??? There is a function of the same name in the C++ front end that + does something similar, but is more thorough and does not return NULL + if no change. We could perhaps share code, but it would make the + self_promoting_type property harder to identify. */ + +tree +simple_type_promotes_to (type) + tree type; +{ + if (TYPE_MAIN_VARIANT (type) == float_type_node) + return double_type_node; + + if (C_PROMOTING_INTEGER_TYPE_P (type)) + { + /* Traditionally, unsignedness is preserved in default promotions. + Also preserve unsignedness if not really getting any wider. */ + if (TREE_UNSIGNED (type) + && (flag_traditional + || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))) + return unsigned_type_node; + return integer_type_node; + } + + return NULL_TREE; +} + +/* Return 1 if PARMS specifies a fixed number of parameters + and none of their types is affected by default promotions. */ + +int +self_promoting_args_p (parms) + tree parms; +{ + register tree t; + for (t = parms; t; t = TREE_CHAIN (t)) + { + register tree type = TREE_VALUE (t); + if (TREE_CHAIN (t) == 0 && type != void_type_node) + return 0; + + if (type == 0) + return 0; + + if (TYPE_MAIN_VARIANT (type) == float_type_node) + return 0; + + if (C_PROMOTING_INTEGER_TYPE_P (type)) + return 0; + } + return 1; +} diff --git a/gcc/c-common.h b/gcc/c-common.h index ab0cdecbd37..7514092b5eb 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -192,3 +192,17 @@ extern void c_common_nodes_and_builtins PROTO((int, int, int)); extern tree build_va_arg PROTO((tree, tree)); extern tree initializer_constant_valid_p PROTO((tree, tree)); + +/* Nonzero if the type T promotes to itself. + ANSI C states explicitly the list of types that promote; + in particular, short promotes to int even if they have the same width. */ +#define C_PROMOTING_INTEGER_TYPE_P(t) \ + (TREE_CODE ((t)) == INTEGER_TYPE \ + && (TYPE_MAIN_VARIANT (t) == char_type_node \ + || TYPE_MAIN_VARIANT (t) == signed_char_type_node \ + || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node \ + || TYPE_MAIN_VARIANT (t) == short_integer_type_node \ + || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node)) + +extern int self_promoting_args_p PROTO((tree)); +extern tree simple_type_promotes_to PROTO((tree)); diff --git a/gcc/c-decl.c b/gcc/c-decl.c index c2d04c1a680..eecc4f6e741 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -1664,8 +1664,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level) break; } - if (TYPE_MAIN_VARIANT (type) == float_type_node - || C_PROMOTING_INTEGER_TYPE_P (type)) + if (simple_type_promotes_to (type) != NULL_TREE) { error ("An argument type that has a default promotion can't match an empty parameter name list declaration."); break; @@ -4858,7 +4857,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) if (decl_context == PARM) { tree type_as_written = type; - tree main_type; + tree promoted_type; /* A parameter declared as an array of T is really a pointer to T. One declared as a function is really a pointer to a function. */ @@ -4892,25 +4891,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) (For example, shorts and chars are passed as ints.) When there is a prototype, this is overridden later. */ - DECL_ARG_TYPE (decl) = type; - main_type = (type == error_mark_node - ? error_mark_node - : TYPE_MAIN_VARIANT (type)); - if (main_type == float_type_node) - DECL_ARG_TYPE (decl) = double_type_node; - /* Don't use TYPE_PRECISION to decide whether to promote, - because we should convert short if it's the same size as int, - but we should not convert long if it's the same size as int. */ - else if (TREE_CODE (main_type) != ERROR_MARK - && C_PROMOTING_INTEGER_TYPE_P (main_type)) + if (type == error_mark_node) + promoted_type = type; + else { - if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node) - && TREE_UNSIGNED (type)) - DECL_ARG_TYPE (decl) = unsigned_type_node; - else - DECL_ARG_TYPE (decl) = integer_type_node; + promoted_type = simple_type_promotes_to (type); + if (! promoted_type) + promoted_type = type; } + DECL_ARG_TYPE (decl) = promoted_type; DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written; } else if (decl_context == FIELD) diff --git a/gcc/c-tree.h b/gcc/c-tree.h index a55785538c6..44ec800cc00 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -145,17 +145,6 @@ struct lang_type /* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */ #define DECL_C_BIT_FIELD(NODE) DECL_LANG_FLAG_4 (NODE) -/* Nonzero if the type T promotes to itself. - ANSI C states explicitly the list of types that promote; - in particular, short promotes to int even if they have the same width. */ -#define C_PROMOTING_INTEGER_TYPE_P(t) \ - (TREE_CODE ((t)) == INTEGER_TYPE \ - && (TYPE_MAIN_VARIANT (t) == char_type_node \ - || TYPE_MAIN_VARIANT (t) == signed_char_type_node \ - || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node \ - || TYPE_MAIN_VARIANT (t) == short_integer_type_node \ - || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node)) - /* In a VAR_DECL, means the variable is really an iterator. */ #define ITERATOR_P(D) (DECL_LANG_FLAG_4(D)) @@ -260,7 +249,6 @@ extern void incomplete_type_error PROTO((tree, tree)); Given two compatible ANSI C types, returns the merged type. */ extern tree common_type PROTO((tree, tree)); extern int comptypes PROTO((tree, tree)); -extern int self_promoting_args_p PROTO((tree)); extern tree c_sizeof PROTO((tree)); extern tree c_sizeof_nowarn PROTO((tree)); extern tree c_size_in_bytes PROTO((tree)); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 72885ebdeb4..7d9352a27d9 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -48,7 +48,6 @@ static tree qualify_type PROTO((tree, tree)); static int comp_target_types PROTO((tree, tree)); static int function_types_compatible_p PROTO((tree, tree)); static int type_lists_compatible_p PROTO((tree, tree)); -static int self_promoting_type_p PROTO((tree)); static tree decl_constant_value PROTO((tree)); static tree lookup_field PROTO((tree, tree, tree *)); static tree convert_arguments PROTO((tree, tree, tree, tree)); @@ -626,12 +625,12 @@ type_lists_compatible_p (args1, args2) So match anything that self-promotes. */ if (TREE_VALUE (args1) == 0) { - if (! self_promoting_type_p (TREE_VALUE (args2))) + if (simple_type_promotes_to (TREE_VALUE (args2)) != NULL_TREE) return 0; } else if (TREE_VALUE (args2) == 0) { - if (! self_promoting_type_p (TREE_VALUE (args1))) + if (simple_type_promotes_to (TREE_VALUE (args1)) != NULL_TREE) return 0; } else if (! (newval = comptypes (TREE_VALUE (args1), TREE_VALUE (args2)))) @@ -680,48 +679,6 @@ type_lists_compatible_p (args1, args2) args2 = TREE_CHAIN (args2); } } - -/* Return 1 if PARMS specifies a fixed number of parameters - and none of their types is affected by default promotions. */ - -int -self_promoting_args_p (parms) - tree parms; -{ - register tree t; - for (t = parms; t; t = TREE_CHAIN (t)) - { - register tree type = TREE_VALUE (t); - - if (TREE_CHAIN (t) == 0 && type != void_type_node) - return 0; - - if (type == 0) - return 0; - - if (TYPE_MAIN_VARIANT (type) == float_type_node) - return 0; - - if (C_PROMOTING_INTEGER_TYPE_P (type)) - return 0; - } - return 1; -} - -/* Return 1 if TYPE is not affected by default promotions. */ - -static int -self_promoting_type_p (type) - tree type; -{ - if (TYPE_MAIN_VARIANT (type) == float_type_node) - return 0; - - if (C_PROMOTING_INTEGER_TYPE_P (type)) - return 0; - - return 1; -} /* Compute the value of the `sizeof' operator. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5ee46749a92..55c4045c664 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +1999-09-07 Richard Henderson + + * cp-tree.h (C_PROMOTING_INTEGER_TYPE_P): Delete. + * typeck.c (self_promoting_args_p): Delete. + 1999-09-07 Jason Merrill * search.c (binfo_for_vtable): Use CLASSTYPE_VFIELD_PARENT. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d7ca7a7ea80..5b6e8f5754c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1902,17 +1902,6 @@ extern int flag_new_for_scope; #define SET_DECL_C_BIT_FIELD(NODE) \ (DECL_LANG_SPECIFIC (NODE)->decl_flags.bitfield = 1) -/* Nonzero if the type T promotes to itself. - ANSI C states explicitly the list of types that promote; - in particular, short promotes to int even if they have the same width. */ -#define C_PROMOTING_INTEGER_TYPE_P(t) \ - (TREE_CODE ((t)) == INTEGER_TYPE \ - && (TYPE_MAIN_VARIANT (t) == char_type_node \ - || TYPE_MAIN_VARIANT (t) == signed_char_type_node \ - || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node \ - || TYPE_MAIN_VARIANT (t) == short_integer_type_node \ - || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node)) - #define INTEGRAL_CODE_P(CODE) \ (CODE == INTEGER_TYPE || CODE == ENUMERAL_TYPE || CODE == BOOLEAN_TYPE) @@ -3751,7 +3740,6 @@ extern int compparms PROTO((tree, tree)); extern int comp_target_types PROTO((tree, tree, int)); extern int comp_cv_qualification PROTO((tree, tree)); extern int comp_cv_qual_signature PROTO((tree, tree)); -extern int self_promoting_args_p PROTO((tree)); extern tree unsigned_type PROTO((tree)); extern tree signed_type PROTO((tree)); extern tree signed_or_unsigned_type PROTO((int, tree)); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 0a8eb8703f0..6b0bc3b0657 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1623,33 +1623,6 @@ comp_target_parms (parms1, parms2, strict) } return warn_contravariance ? -1 : 1; } - -/* Return 1 if PARMS specifies a fixed number of parameters - and none of their types is affected by default promotions. */ - -int -self_promoting_args_p (parms) - tree parms; -{ - register tree t; - for (t = parms; t; t = TREE_CHAIN (t)) - { - register tree type = TREE_VALUE (t); - - if (TREE_CHAIN (t) == 0 && type != void_type_node) - return 0; - - if (type == 0) - return 0; - - if (TYPE_MAIN_VARIANT (type) == float_type_node) - return 0; - - if (C_PROMOTING_INTEGER_TYPE_P (type)) - return 0; - } - return 1; -} /* Compute the value of the `sizeof' operator. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d9272e616b4..f05eb74ba0d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +1999-09-07 Richard Henderson + + * gcc.dg/va-arg-1.c: New. + 1999-09-05 Craig Burley * g77.f-torture/compile/980519-2.f: New test. diff --git a/gcc/testsuite/gcc.dg/va-arg-1.c b/gcc/testsuite/gcc.dg/va-arg-1.c new file mode 100644 index 00000000000..b29d7eb7f29 --- /dev/null +++ b/gcc/testsuite/gcc.dg/va-arg-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ + +#include + +va_list v; +volatile int i; + +void foo() +{ + i = va_arg(v, char); /* { dg-error "is promoted to|so you should" "char" } */ + i = va_arg(v, short); /* { dg-error "is promoted to" "short" } */ + i = va_arg(v, float); /* { dg-error "is promoted to" "float" } */ +} diff --git a/gcc/tree.h b/gcc/tree.h index 6251fa6d8ae..e1e04792dac 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2040,6 +2040,12 @@ extern void rrotate_double PROTO((HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT *)); extern int operand_equal_p PROTO((tree, tree, int)); extern tree invert_truthvalue PROTO((tree)); + +/* In builtins.c. Given a type, apply default promotions wrt unnamed + function arguments and return the new type. Return NULL_TREE if no + change. Required by any language that supports variadic arguments. */ + +extern tree (*lang_type_promotes_to) PROTO((tree)); /* Interface of the DWARF2 unwind info support. */ -- 2.30.2