C++ PATCHES for various buglets

Mark Mitchell mark@markmitchell.com
Wed Jan 20 13:09:00 GMT 1999


This patch fixes the following things:

  o Statement-expressions in templates could result in memory
    corruption.

  o Passing a variable-sized array to a template function could result
    in a crash.

  o We didn't obey __attribute__ ((format)) on a member function.

  o We printed expressions like `f(3)' as `f(int)(3)'.

-- 
Mark Mitchell 			mark@markmitchell.com
Mark Mitchell Consulting	http://www.markmitchelnl.com

1999-01-20  Mark Mitchell  <mark@markmitchell.com>

	* error.c (dump_function_decl): Don't print the argument types for
	a function when the verbosity level is negative.
	
	* call.c (build_over_call): Check format attributes at call-time.

	* pt.c (tsubst_copy): Fix comment.
	(unify): Don't allow unification with variable-sized arrays.

	* semantics.c (finish_stmt_expr): When processing a template make
	the BIND_EXPR long-lived.

Index: testsuite/g++.old-deja/g++.pt/crash27.C
===================================================================
RCS file: crash27.C
diff -N crash27.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- crash27.C	Wed Jan 20 13:01:54 1999
***************
*** 0 ****
--- 1,13 ----
+ // Build don't link:
+ 
+ template<int i> int f (void)
+ {
+         if (__extension__ ({ 1; }))
+                 return 0;
+         return 1;
+ }
+ 
+ void g (void)
+ {
+         f<1> ();
+ }
Index: testsuite/g++.old-deja/g++.pt/crash28.C
===================================================================
RCS file: crash28.C
diff -N crash28.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- crash28.C	Wed Jan 20 13:01:54 1999
***************
*** 0 ****
--- 1,14 ----
+ // Build don't link:
+ // Special g++ Options:
+ 
+ template <class ARRY>
+ inline unsigned int asize(ARRY &a)
+ {
+   return sizeof(a) / sizeof(a[0]);
+ }
+ 
+ int f(unsigned int n) {
+   int x[n];
+ 
+   asize(x); // ERROR - no matching function
+ };
Index: testsuite/g++.old-deja/g++.other/printf1.C
===================================================================
RCS file: printf1.C
diff -N printf1.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- printf1.C	Wed Jan 20 13:01:54 1999
***************
*** 0 ****
--- 1,14 ----
+ // Build don't link:
+ // Special g++ Options: -Wall
+ 
+ struct a
+ {
+   void x(char *f,...) __attribute__((format(printf,2,3)));
+ };
+ 
+ int main()
+ {
+   a A;
+   A.x("%d"); // WARNING - too few arguments for format
+   return 0;
+ }
Index: cp/call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.127
diff -c -p -r1.127 call.c
*** call.c	1998/12/16 21:15:05	1.127
--- call.c	1999/01/20 21:01:56
*************** build_over_call (cand, args, flags)
*** 3364,3369 ****
--- 3364,3373 ----
  
    converted_args = nreverse (converted_args);
  
+   if (warn_format && (DECL_NAME (fn) || DECL_ASSEMBLER_NAME (fn)))
+     check_function_format (DECL_NAME (fn), DECL_ASSEMBLER_NAME (fn),
+ 			   converted_args); 
+ 
    /* Avoid actually calling copy constructors and copy assignment operators,
       if possible.  */
  
Index: cp/error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.65
diff -c -p -r1.65 error.c
*** error.c	1998/12/18 11:26:57	1.65
--- error.c	1999/01/20 21:01:57
*************** dump_decl (t, v)
*** 958,965 ****
  }
  
  /* Pretty printing for announce_function.  T is the declaration of the
!    function we are interested in seeing.  V is non-zero if we should print
!    the type that this function returns.  */
  
  static void
  dump_function_decl (t, v)
--- 958,966 ----
  }
  
  /* Pretty printing for announce_function.  T is the declaration of the
!    function we are interested in seeing.  If V is zero, we print the
!    argument types.  If V is positive, we also print the return types.
!    If V is negative, we do not even print the argument types.  */
  
  static void
  dump_function_decl (t, v)
*************** dump_function_decl (t, v)
*** 985,993 ****
    else if (TREE_CODE (fntype) == METHOD_TYPE)
      cname = TREE_TYPE (TREE_VALUE (parmtypes));
  
!   v = (v > 0);
!   
!   if (v)
      {
        if (DECL_STATIC_FUNCTION_P (t))
  	OB_PUTS ("static ");
--- 986,993 ----
    else if (TREE_CODE (fntype) == METHOD_TYPE)
      cname = TREE_TYPE (TREE_VALUE (parmtypes));
  
!   /* Print the return type.  */
!   if (v > 0)
      {
        if (DECL_STATIC_FUNCTION_P (t))
  	OB_PUTS ("static ");
*************** dump_function_decl (t, v)
*** 1001,1006 ****
--- 1001,1007 ----
  	}
      }
  
+   /* Print the function name.  */
    if (cname)
      {
        dump_type (cname, 0);
*************** dump_function_decl (t, v)
*** 1021,1027 ****
      parmtypes = TREE_CHAIN (parmtypes);
    
    dump_function_name (t);
!   
    OB_PUTC ('(');
  
    if (parmtypes)
--- 1022,1032 ----
      parmtypes = TREE_CHAIN (parmtypes);
    
    dump_function_name (t);
! 
!   /* If V is negative, we don't print the argument types.  */
!   if (v < 0)
!     return;
! 
    OB_PUTC ('(');
  
    if (parmtypes)
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.252
diff -c -p -r1.252 pt.c
*** pt.c	1999/01/18 13:32:54	1.252
--- pt.c	1999/01/20 21:02:07
*************** tsubst_copy (t, args, in_decl)
*** 6329,6335 ****
  
  	if (code == BIND_EXPR && !processing_template_decl)
  	  {
! 	    /* This processing  should really occur in tsubst_expr,
  	       However, tsubst_expr does not recurse into expressions,
  	       since it assumes that there aren't any statements
  	       inside them.  Instead, it simply calls
--- 6329,6335 ----
  
  	if (code == BIND_EXPR && !processing_template_decl)
  	  {
! 	    /* This processing should really occur in tsubst_expr,
  	       However, tsubst_expr does not recurse into expressions,
  	       since it assumes that there aren't any statements
  	       inside them.  Instead, it simply calls
*************** unify (tparms, targs, parm, arg, strict,
*** 7504,7509 ****
--- 7504,7523 ----
  	return 0;
        else if (targ)
  	return 1;
+ 
+       /* Make sure that ARG is not a variable-sized array.  (Note that
+ 	 were talking about variable-sized arrays (like `int[n]'),
+ 	 rather than arrays of unknown size (like `int[]').)  We'll
+ 	 get very confused by such a type since the bound of the array
+ 	 will not be computable in an instantiation.  Besides, such
+ 	 types are not allowed in ISO C++, so we can do as we please
+ 	 here.  */
+       if (TREE_CODE (arg) == ARRAY_TYPE 
+ 	  && !uses_template_parms (arg)
+ 	  && (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (arg)))
+ 	      != INTEGER_CST))
+ 	return 1;
+ 
        TREE_VEC_ELT (targs, idx) = arg;
        return 0;
  
Index: cp/semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.39
diff -c -p -r1.39 semantics.c
*** semantics.c	1999/01/14 10:42:12	1.39
--- semantics.c	1999/01/20 21:02:08
*************** finish_stmt_expr (rtl_expr, expr)
*** 809,816 ****
      {
        /* Make a BIND_EXPR for the BLOCK already made.  */
        if (processing_template_decl)
! 	result = build (BIND_EXPR, NULL_TREE,
! 			NULL_TREE, last_tree, expr);
        else
  	result = build (BIND_EXPR, TREE_TYPE (rtl_expr),
  			NULL_TREE, rtl_expr, expr);
--- 809,816 ----
      {
        /* Make a BIND_EXPR for the BLOCK already made.  */
        if (processing_template_decl)
! 	result = build_min_nt (BIND_EXPR, NULL_TREE, last_tree,
! 			       NULL_TREE);
        else
  	result = build (BIND_EXPR, TREE_TYPE (rtl_expr),
  			NULL_TREE, rtl_expr, expr);



More information about the Gcc-patches mailing list