C++ PATCH: check throw validity

Nathan Sidwell nathan@acm.org
Thu Jun 3 06:56:00 GMT 1999


Hi,
the recent tests added by Robert Lipe (eh990323-[1-5].C and ice990323-[1-5].C)
cause failures. There are four reasons, and this patch addresses 2 of them

1) there were some missing //ERROR markers in the tests - I've added them

2) we didn't enforce 15.1/3 (thou shall not throw an incomplete type ...) and
died horribly. This patch fixes build_throw to do so.

3) some template cleanups are not being invoked - I've not investigated.

4) __cplus_type_matcher, __throw_type_match_rtti etc return the adjusted type
to catch on success or NULL on failure. If you throw a NULL ptr things go sadly
wrong.

I can't find wording disallowing throwing (T *)NULL, and believe it valid. To
fix this requires changing __cplus_type_matcher etc to return both a
success/failure flag and the adjusted value. (You can't blindly assume NULL
ptrs convert, because that might allow conversion to a private base class.) I'm
working on a patch for that which adds a trailing `void **dst_ptr' argument to
the associated functions. I plan to keep the `void *' return type, even though
an int return would be more logical. Unfortunately this problem goes rather
deep into tinfo2.cc as well. I'll submit that if/when it's ready. (Shout now if
you think I'm wasting my time/going about this the wrong way :-)

Ok to install?

nathan
-- 
Dr Nathan Sidwell :: Computer Science Department :: Bristol University
        I have seen the death of PhotoShop -- it is called GIMP
nathan@acm.org  http://www.cs.bris.ac.uk/~nathan/  nathan@cs.bris.ac.uk
1999-06-03  Nathan Sidwell  <nathan@acm.org>

	* except.c (build_throw): Check throw expression validity.

Index: egcs/gcc/cp/except.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/except.c,v
retrieving revision 1.63
diff -c -3 -p -r1.63 except.c
*** except.c	1999/03/26 07:44:28	1.63
--- except.c	1999/06/03 12:59:25
*************** build_throw (e)
*** 1152,1157 ****
--- 1152,1184 ----
  
    if (e == null_node)
      cp_warning ("throwing NULL, which has integral, not pointer type");
+   
+   if (e != NULL_TREE)
+     {
+       tree core;
+       int is_ptr;
+       
+       /* Cannot throw an incomplete type. */
+       e = require_complete_type (e);
+       if (e == error_mark_node)
+         return e;
+       
+       /* Or a pointer or ref to one, other than cv void *.  */
+       core = TREE_TYPE (e);
+       is_ptr = TREE_CODE (core) == POINTER_TYPE;
+       if (is_ptr || TREE_CODE (core) == REFERENCE_TYPE)
+         {
+           core = TREE_TYPE (core);
+       
+           if (is_ptr && TYPE_MAIN_VARIANT (core) == void_type_node)
+             /* OK */;
+           else if (TYPE_SIZE (core) == NULL_TREE)
+             {
+               incomplete_type_error (NULL_TREE, core);
+               return error_mark_node;
+             }
+         }
+     }
  
    e = build1 (THROW_EXPR, void_type_node, e);
    TREE_SIDE_EFFECTS (e) = 1;
Index: egcs/gcc/testsuite/g++.old-deja/g++.robertl/eh990323-1.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.robertl/eh990323-1.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 eh990323-1.C
*** eh990323-1.C	1999/05/28 13:26:49	1.1
--- eh990323-1.C	1999/06/03 13:00:18
*************** template <class T> void ff(T)
*** 17,23 ****
  {
  }
  
! void g(void)
  {
  }
  
--- 17,23 ----
  {
  }
  
! void g(int)
  {
  }
  
Index: egcs/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-1.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-1.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 ice990323-1.C
*** ice990323-1.C	1999/05/28 13:26:49	1.1
--- ice990323-1.C	1999/06/03 13:00:18
***************
*** 1,7 ****
  //test 2
  struct A {};
  void f()
  {
!         struct A;
!         throw *(new A);
  }
--- 1,9 ----
+ // Build don't link:
+ 
  //test 2
  struct A {};
  void f()
  {
!         struct A; // ERROR - forward ref
!         throw *(new A); // ERROR - invalid use of undefined type
  }
Index: egcs/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-2.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-2.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 ice990323-2.C
*** ice990323-2.C	1999/05/28 13:26:49	1.1
--- ice990323-2.C	1999/06/03 13:00:18
*************** void f4()
*** 25,31 ****
  	throw A<double, 47, A<int, 36, short> > ("hi michey");
  }
  
! main()
  {
  	int flag;
  
--- 25,31 ----
  	throw A<double, 47, A<int, 36, short> > ("hi michey");
  }
  
! int main()
  {
  	int flag;
  
Index: egcs/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-3.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-3.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 ice990323-3.C
*** ice990323-3.C	1999/05/28 13:26:49	1.1
--- ice990323-3.C	1999/06/03 13:00:18
***************
*** 1,3 ****
--- 1,4 ----
+ // Build don't link:
  // try throwing overloaded function
  
  void f(int)
*************** void f(long)
*** 10,14 ****
  
  void g()
  {
! 	throw &f;
  }
--- 11,15 ----
  
  void g()
  {
! 	throw &f; // ERROR - insufficient contextual information
  }
Index: egcs/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-4.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-4.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 ice990323-4.C
*** ice990323-4.C	1999/05/28 13:26:49	1.1
--- ice990323-4.C	1999/06/03 13:00:18
***************
*** 1,3 ****
--- 1,4 ----
+ // Build don't link:
  // try throwing template function name
  
  template <class T> void f(T);
*************** template <class T> void f(T)
*** 8,12 ****
  
  void g()
  {
! 	throw &f;
  }
--- 9,13 ----
  
  void g()
  {
! 	throw &f; // ERROR - insufficient contextual information
  }
Index: egcs/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-5.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.robertl/ice990323-5.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 ice990323-5.C
*** ice990323-5.C	1999/05/28 13:26:49	1.1
--- ice990323-5.C	1999/06/03 13:00:18
***************
*** 1,3 ****
--- 1,4 ----
+ // Build don't link:
  // check attempting to throw an overloaded function
  
  struct A {
*************** struct A {
*** 7,11 ****
  
  void g()
  {
! 	throw &A::f;
  }
--- 8,12 ----
  
  void g()
  {
! 	throw &A::f; // ERROR - insufficient context
  }


More information about the Gcc-patches mailing list