This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

va_list: rfc: invalid types


While going through these va_arg conversions, I've been struck by how
badly some of them can get confused by illegal types being sent through
them, and how many va-foo.h implementors forget that `float' isn't a
valid thing to be asking for from va_arg.

With a little tweek here and there I'm able to give a diagnostic when
someone does something silly with va_list --

    i = va_arg(v, char);
    i = va_arg(v, short);
    i = va_arg(v, float);
  
  y.c:7: `char' subject to type promotion in varargs
  y.c:8: `short int' subject to type promotion in varargs
  y.c:9: `float' subject to type promotion in varargs

The question to the group is what sort of diagnostic?  My favourite is
to go ahead and make this an error cause we know up front it isn't going
to work.  Someone of a less idealistic and more forgiving bent might
just make this a warning.

Then there's the question of wording.  I don't like what I have, but
can't think how better to express it.



r~


gcc/
	* builtins.c (lang_self_promoting_type_p): Define.
	(expand_builtin_va_arg): Error if the type is subject to promotion.
	* c-typeck.c (self_promoting_type_p, self_promoting_args_p): Move ...
	* c-common.c: ... here.
	(c_common_nodes_and_builtins): Initialize lang_self_promoting_type_p.
	* c-tree.h (C_PROMOTING_INTEGER_TYPE_P): Moved ...
	* c-common.h: ... here.
	(self_promoting_args_p): Declare.
	(self_promoting_type_p): Declare.
	* expr.h (lang_self_promoting_type_p): Declare.

cp/
	* cp-tree.h (C_PROMOTING_INTEGER_TYPE_P): Kill.
	(self_promoting_args_p): Kill.	
	* typeck.c (self_promoting_args_p): Kill.
	
Index: builtins.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/builtins.c,v
retrieving revision 1.9
diff -c -p -d -r1.9 builtins.c
*** builtins.c	1999/08/26 05:18:40	1.9
--- builtins.c	1999/09/06 00:43:05
*************** Boston, MA 02111-1307, USA.  */
*** 52,57 ****
--- 52,59 ----
  #define OUTGOING_REGNO(IN) (IN)
  #endif
  
+ int (*lang_self_promoting_type_p) PROTO((tree));
+ 
  static int get_pointer_alignment	PROTO((tree, unsigned));
  static tree c_strlen			PROTO((tree));
  static rtx get_memory_rtx		PROTO((tree));
*************** expand_builtin_va_arg (valist, type)
*** 1976,1982 ****
    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'");
        addr = const0_rtx;
      }
    else
--- 1978,2004 ----
    if (TYPE_MAIN_VARIANT (TREE_TYPE (valist))
        != TYPE_MAIN_VARIANT (va_list_type_node))
      {
!       error ("first argument to `va_arg' not of type `va_list'");
!       addr = const0_rtx;
!     }
!   else if (! lang_self_promoting_type_p)
!     abort ();
!   else if (! (*lang_self_promoting_type_p) (type))
!     {
!       const char *name = NULL;
!       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 (name)
! 	error ("`%s' subject to type promotion in varargs", name);
!       else
! 	error ("second argument to `va_arg' subject to type promotion");
        addr = const0_rtx;
      }
    else
Index: c-common.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-common.c,v
retrieving revision 1.66
diff -c -p -d -r1.66 c-common.c
*** c-common.c	1999/08/25 21:05:16	1.66
--- c-common.c	1999/09/06 00:43:05
*************** Boston, MA 02111-1307, USA.  */
*** 29,34 ****
--- 29,35 ----
  #include "output.h"
  #include "c-pragma.h"
  #include "rtl.h"
+ #include "expr.h"
  
  #if USE_CPPLIB
  #include "cpplib.h"
*************** c_common_nodes_and_builtins (cplus_mode,
*** 3803,3808 ****
--- 3804,3813 ----
    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_self_promoting_type_p = self_promoting_type_p;
  }
  
  tree
*************** initializer_constant_valid_p (value, end
*** 3966,3969 ****
--- 3971,4012 ----
  
    return 0;
  }
+ 
+ /* Return 1 if TYPE is not affected by default promotions.  */
+ 
+ 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;
+ }
  
+ /* 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 (! self_promoting_type_p (type))
+ 	return 0;
+     }
+   return 1;
+ }
Index: c-common.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-common.h,v
retrieving revision 1.4
diff -c -p -d -r1.4 c-common.h
*** c-common.h	1999/07/31 01:13:08	1.4
--- c-common.h	1999/09/06 00:43:05
*************** extern void c_common_nodes_and_builtins	
*** 192,194 ****
--- 192,208 ----
  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 int self_promoting_type_p		PROTO((tree));
Index: c-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-tree.h,v
retrieving revision 1.24
diff -c -p -d -r1.24 c-tree.h
*** c-tree.h	1999/09/05 01:06:45	1.24
--- c-tree.h	1999/09/06 00:43:05
*************** struct lang_type
*** 145,161 ****
  /* 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))
  
--- 145,150 ----
*************** extern void incomplete_type_error		PROTO
*** 256,262 ****
     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));
--- 245,250 ----
Index: c-typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-typeck.c,v
retrieving revision 1.34
diff -c -p -d -r1.34 c-typeck.c
*** c-typeck.c	1999/08/27 07:37:15	1.34
--- c-typeck.c	1999/09/06 00:43:05
*************** static tree qualify_type		PROTO((tree, t
*** 48,54 ****
  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));
--- 48,53 ----
*************** type_lists_compatible_p (args1, args2)
*** 679,726 ****
        args1 = TREE_CHAIN (args1);
        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.  */
--- 678,683 ----
Index: expr.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.h,v
retrieving revision 1.45
diff -c -p -d -r1.45 expr.h
*** expr.h	1999/09/05 03:49:51	1.45
--- expr.h	1999/09/06 00:43:05
*************** extern rtx expand_builtin PROTO((tree, r
*** 863,868 ****
--- 863,869 ----
  extern void std_expand_builtin_va_start PROTO((int, tree, rtx));
  extern rtx std_expand_builtin_va_arg PROTO((tree, tree));
  extern rtx expand_builtin_va_arg PROTO((tree, tree));
+ extern int (*lang_self_promoting_type_p) PROTO((tree));
  #endif
  
  extern rtx expand_builtin_setjmp PROTO((rtx, rtx, rtx, rtx));
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.285
diff -c -p -d -r1.285 cp-tree.h
*** cp-tree.h	1999/09/05 16:21:25	1.285
--- cp-tree.h	1999/09/06 00:43:06
*************** extern int flag_new_for_scope;
*** 1742,1758 ****
  #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)
  
--- 1742,1747 ----
*************** extern int compparms				PROTO((tree, tre
*** 3638,3644 ****
  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));
--- 3627,3632 ----
Index: cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.202
diff -c -p -d -r1.202 typeck.c
*** typeck.c	1999/09/04 02:19:29	1.202
--- typeck.c	1999/09/06 00:43:06
*************** comp_target_parms (parms1, parms2, stric
*** 1623,1655 ****
      }
    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.  */
  
--- 1623,1628 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]