c-typeck.c (type_lists_compatible_p): Use simple_type_promotes_to.
authorRichard Henderson <rth@cygnus.com>
Wed, 8 Sep 1999 04:51:16 +0000 (21:51 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 8 Sep 1999 04:51:16 +0000 (21:51 -0700)
        * 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

13 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/c-common.c
gcc/c-common.h
gcc/c-decl.c
gcc/c-tree.h
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/va-arg-1.c [new file with mode: 0644]
gcc/tree.h

index f1425e91780951e6562b97c5062f0997d8402989..5770cfdb5ed1bac191d7c22288ee236aeb20beb4 100644 (file)
@@ -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.
index c4e36059d07094c64ebcc0fc2a84204189f4f6ba..ebd7b12abd80bf0c176ba989f8570d162821d36f 100644 (file)
@@ -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
index 4fea4ac70aed22f508807aa37a4be2567b73a526..3de1e9265a1df09d680d67c9653fb8c853f5e3da 100644 (file)
@@ -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;
 }
+\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;
+}
index ab0cdecbd37484104df71eafa343fc37694fc3c9..7514092b5ebe6eae5c227e005a64f92c5fc06927 100644 (file)
@@ -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));
index c2d04c1a6804e366d9f89af601e0ff90e0ec41f8..eecc4f6e7419aa04eaa91a22b1bd073b5d8a4448 100644 (file)
@@ -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)
index a55785538c6e6dc13fa2b4f394f0f661772f7bf8..44ec800cc00848709880f27b1ce1a0808ad24ef5 100644 (file)
@@ -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));
index 72885ebdeb49a43c5cd401320715ee1ccfa0da3c..7d9352a27d9d25dadf6a106554697027c765a117 100644 (file)
@@ -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;
-}
 \f
 /* Compute the value of the `sizeof' operator.  */
 
index 5ee46749a92e2b0266d929dc49de77d962db4d59..55c4045c66494501c8096ce6ad62015312bdfd77 100644 (file)
@@ -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.
index d7ca7a7ea80feb577e90473ed9ac6f3a1cbf8f59..5b6e8f5754c829c995c2b64688d0c9ddd909212f 100644 (file)
@@ -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));
index 0a8eb8703f0465c5d2bc8ba066eedd1ef4dbd247..6b0bc3b065784fbfb883e9c0f6fe3f924e017c92 100644 (file)
@@ -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;
-}
 \f
 /* Compute the value of the `sizeof' operator.  */
 
index d9272e616b442d328519db6a139105995cea9bf9..f05eb74ba0d90e8dde03a6e8ea264786ca58dff9 100644 (file)
@@ -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 (file)
index 0000000..b29d7eb
--- /dev/null
@@ -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" } */
+}
index 6251fa6d8aeb54f1e6766a03576e373b935dbd00..e1e04792dac6693157c6b5b9ee06de4fc702827a 100644 (file)
@@ -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));
 \f
 /* Interface of the DWARF2 unwind info support.  */