aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/builtins.c36
-rw-r--r--gcc/c-common.c58
-rw-r--r--gcc/c-common.h14
-rw-r--r--gcc/c-decl.c28
-rw-r--r--gcc/c-tree.h12
-rw-r--r--gcc/c-typeck.c47
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/cp-tree.h12
-rw-r--r--gcc/cp/typeck.c27
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/va-arg-1.c13
-rw-r--r--gcc/tree.h6
13 files changed, 163 insertions, 116 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f1425e9..5770cfd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+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.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index c4e3605..ebd7b12 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 = "<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
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 4fea4ac..3de1e92 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 ab0cdec..7514092 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 c2d04c1..eecc4f6 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 a557855..44ec800 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 72885eb..7d9352a 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 5ee4674..55c4045 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d7ca7a7..5b6e8f5 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 0a8eb87..6b0bc3b 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 d9272e6..f05eb74 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+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.
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 0000000..b29d7eb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/va-arg-1.c
@@ -0,0 +1,13 @@
+/* { 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" } */
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index 6251fa6..e1e0479 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. */