* 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
+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.
#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));
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
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
return 0;
}
+\f
+/* 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;
+}
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));
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;
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. */
(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)
/* 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))
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));
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));
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))))
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;
-}
\f
/* 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.
#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)
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));
}
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;
-}
\f
/* 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.
--- /dev/null
+/* { 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" } */
+}
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));
\f
/* Interface of the DWARF2 unwind info support. */