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]
Other format: [Raw text]

C++ PATCH: PR 13009


This patch fixes a problem with implicitly generated assignment
operators for classes with a virtual base.  (Such operators are rare
because of the fact that the standard doesn't specify whether implicit
assignment operators assign more than once to virtual bases;
therefore, in inheritance heirarchies with virtual bases most people
write their own assignment operators.)

When such an assignment operator *is* generated, however, we must
realize that the location of the virtual base cannot be found
statically.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2003-12-28  Mark Mitchell  <mark@codesourcery.com>

	PR c++/13009
	* call.c (build_special_member_call): Do not assume that we have a
	pointer to the complete object in an assignment operator.

2003-12-28  Mark Mitchell  <mark@codesourcery.com>

	PR c++/13009
	* g++.dg/init/assign1.C: New test.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.446
diff -c -5 -p -r1.446 call.c
*** cp/call.c	21 Dec 2003 21:07:29 -0000	1.446
--- cp/call.c	29 Dec 2003 01:27:44 -0000
*************** build_special_member_call (tree instance
*** 4863,4880 ****
        if (name == complete_dtor_identifier 
  	  || name == base_dtor_identifier
  	  || name == deleting_dtor_identifier)
  	my_friendly_assert (args == NULL_TREE, 20020712);
  
!       /* We must perform the conversion here so that we do not
! 	 subsequently check to see whether BINFO is an accessible
! 	 base.  (It is OK for a constructor to call a constructor in
! 	 an inaccessible base as long as the constructor being called
! 	 is accessible.)  */
        if (!same_type_ignoring_top_level_qualifiers_p 
  	  (TREE_TYPE (instance), BINFO_TYPE (binfo)))
! 	instance = convert_to_base_statically (instance, binfo);
      }
    
    my_friendly_assert (instance != NULL_TREE, 20020712);
  
    /* Resolve the name.  */
--- 4863,4889 ----
        if (name == complete_dtor_identifier 
  	  || name == base_dtor_identifier
  	  || name == deleting_dtor_identifier)
  	my_friendly_assert (args == NULL_TREE, 20020712);
  
!       /* Convert to the base class, if necessary.  */
        if (!same_type_ignoring_top_level_qualifiers_p 
  	  (TREE_TYPE (instance), BINFO_TYPE (binfo)))
! 	{
! 	  if (name != ansi_assopname (NOP_EXPR))
! 	    /* For constructors and destructors, either the base is
! 	       non-virtual, or it is virtual but we are doing the
! 	       conversion from a constructor or destructor for the
! 	       complete object.  In either case, we can convert
! 	       statically.  */
! 	    instance = convert_to_base_statically (instance, binfo);
! 	  else
! 	    /* However, for assignment operators, we must convert
! 	       dynamically if the base is virtual.  */
! 	    instance = build_base_path (PLUS_EXPR, instance,
! 					binfo, /*nonnull=*/1);
! 	}
      }
    
    my_friendly_assert (instance != NULL_TREE, 20020712);
  
    /* Resolve the name.  */
Index: testsuite/g++.dg/init/assign1.C
===================================================================
RCS file: testsuite/g++.dg/init/assign1.C
diff -N testsuite/g++.dg/init/assign1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/assign1.C	29 Dec 2003 01:27:45 -0000
***************
*** 0 ****
--- 1,30 ----
+ // PR c++/13009
+ // { dg-do run }
+ 
+ struct A {
+   char a;
+ };
+ 
+ struct B: public virtual A {
+   #if 0 // this piece of code works around the problem
+   B& operator= (const B& other)
+   {
+     A::operator= (other);
+   }
+   #endif
+ };
+ 
+ struct C: public B {
+   char c;
+ };
+ 
+ int main() {
+   B b;
+   b.a = 'b';
+   C c;
+   c.a = c.c = 'c';
+   
+   c.B::operator= (b);
+   if (c.a != 'b' || c.c != 'c')
+     return 1;
+ }


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