Patch for too-lenient handling of pointer-to-member conversions

Mark Mitchell mmitchell@usa.net
Wed Feb 11 15:56:00 GMT 1998


Jason --

  Here's a patch to make sure that we don't allow code like this:

    struct S { void f(int); }
    void (S::*sp)(char*) = &S::f;

  Is it OK to check this in?

-- 
Mark Mitchell		mmitchell@usa.net
Stanford University	http://www.stanford.edu

Wed Feb 11 15:54:18 1998  Mark Mitchell  <mmitchell@usa.net>

	* typeck.c (build_ptrmemfunc): Typecheck pointer-to-member
	conversions.

Index: gcc/cp/typeck.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/typeck.c,v
retrieving revision 1.12
diff -c -p -r1.12 typeck.c
*** typeck.c	1998/02/11 19:03:40	1.12
--- typeck.c	1998/02/11 23:33:03
*************** build_ptrmemfunc (type, pfn, force)
*** 6428,6437 ****
--- 6428,6456 ----
      {
        tree ndelta, ndelta2;
        tree e1, e2, e3, n;
+       tree pfn_type;
  
        /* Is is already the right type? */
        if (type == TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))
  	return pfn;
+ 
+       pfn_type = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn));
+       if (!force
+ 	  && (/* Check the class types.  Recall that a
+ 		 pointer-to-member-of-base can be converted to a
+ 		 pointer-to-member-of-derived but not vice versa.  */
+ 	      !ACCESSIBLY_UNIQUELY_DERIVED_P (TYPE_METHOD_BASETYPE
+ 					      (TREE_TYPE (pfn_type)),
+ 					      TYPE_METHOD_BASETYPE 
+ 					      (TREE_TYPE (type)))
+ 	      /* Check the argument types, except `this'.  */
+ 	      || !compparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (type))), 
+ 			     TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (pfn_type))),
+ 			     1)
+ 	      /* Check the return types.  */
+ 	      || !comptypes (TREE_TYPE (TREE_TYPE (type)),
+ 			     TREE_TYPE (TREE_TYPE (pfn_type)), 1)))
+ 	cp_error ("conversion to `%T' from `%T'", type, pfn_type);
  
        ndelta = cp_convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, NULL_TREE, 0));
        ndelta2 = cp_convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn));
Index: gcc/testsuite/g++.old-deja/g++.mike/p10769a.C
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/testsuite/g++.old-deja/g++.mike/p10769a.C,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 p10769a.C
*** p10769a.C	1997/11/08 17:54:13	1.1.1.1
--- p10769a.C	1998/02/11 23:38:36
*************** dispatch (A *obj, int i, int j)
*** 28,34 ****
  
  void A::main() {
    dispatch (&a, 0, 0);
!   void (A::*mPtr)(A*) = &A::f1a;
  
    (*(void (*)(A*))PMF2PF(mPtr))(&a);
    (*(void (*)(A*))PMF2PF(f2a))(&a);
--- 28,34 ----
  
  void A::main() {
    dispatch (&a, 0, 0);
!   void (A::*mPtr)(A*) = (void (A::*)(A*))&A::f1a;
  
    (*(void (*)(A*))PMF2PF(mPtr))(&a);
    (*(void (*)(A*))PMF2PF(f2a))(&a);
*************** void A::main() {
*** 37,43 ****
  int main() {
    a.A::main();
    dispatch (&a, 0, 1);
!   void (A::*mPtr)(A*) = &A::f1b;
  
    (*(void (*)(A*))PMF2PF(a.*mPtr))(&a);
    (*(void (*)(A*))PMF2PF(a.f2a))(&a);
--- 37,43 ----
  int main() {
    a.A::main();
    dispatch (&a, 0, 1);
!   void (A::*mPtr)(A*) = (void (A::*)(A*))&A::f1b;
  
    (*(void (*)(A*))PMF2PF(a.*mPtr))(&a);
    (*(void (*)(A*))PMF2PF(a.f2a))(&a);
Index: gcc/testsuite/g++.old-deja/g++.mike/p10769b.C
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/testsuite/g++.old-deja/g++.mike/p10769b.C,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 p10769b.C
*** p10769b.C	1997/11/08 17:54:13	1.1.1.1
--- p10769b.C	1998/02/11 23:39:21
*************** void A::main() {
*** 20,25 ****
  }
  
  int main() {
!   void (A::*mPtr)(A*) = &A::f1a;
    (*(void (*)(A*))PMF2PF(mPtr))(&a);	// ERROR - 
  }
--- 20,25 ----
  }
  
  int main() {
!   void (A::*mPtr)(A*) = (void (A::*)(A*)) &A::f1a;
    (*(void (*)(A*))PMF2PF(mPtr))(&a);	// ERROR - 
  }
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.niklas
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.other
Index: gcc/testsuite/g++.old-deja/g++.other/ptrmem2.C
===================================================================
RCS file: ptrmem2.C
diff -N ptrmem2.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- ptrmem2.C	Wed Feb 11 12:50:29 1998
***************
*** 0 ****
--- 1,17 ----
+ class cow {
+ public:
+   void moo (char *);
+ };
+ 
+ void f()
+ {
+   cow* c;
+ 
+   void (cow::*fp0)(char*) = &cow::moo;  // OK
+   void (cow::*fp1)(int) = &cow::moo;    // ERROR - conversion
+   int (cow::*fp2)(char*) = &cow::moo;   // ERROR - conversion
+   int (cow::*fp3)(char*, void*) = fp2;  // ERROR - conversion
+   int (cow::*fp4)(double) = (int (cow::*)(double)) fp2; // OK
+ }
+ 
+  



More information about the Gcc-bugs mailing list