Commit c530479e by Richard Henderson Committed by Richard Henderson

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
parent 472236af
Tue Sep 7 21:41:38 1999 Richard Henderson <rth@cygnus.com>
* 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 <mark@codesourcery.com>
Add some machine-dependent GC roots.
......
......@@ -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 = "<anonymous type>", *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
......
......@@ -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;
}
......@@ -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));
......@@ -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)
......
......@@ -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));
......
......@@ -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. */
......
1999-09-07 Richard Henderson <rth@cygnus.com>
* cp-tree.h (C_PROMOTING_INTEGER_TYPE_P): Delete.
* typeck.c (self_promoting_args_p): Delete.
1999-09-07 Jason Merrill <jason@yorick.cygnus.com>
* search.c (binfo_for_vtable): Use CLASSTYPE_VFIELD_PARENT.
......
......@@ -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));
......
......@@ -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. */
......
1999-09-07 Richard Henderson <rth@cygnus.com>
* gcc.dg/va-arg-1.c: New.
1999-09-05 Craig Burley <craig@jcb-sc.com>
* g77.f-torture/compile/980519-2.f: New test.
......
/* { dg-do compile } */
#include <stdarg.h>
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" } */
}
......@@ -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. */
......
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