OSDN Git Service

PR c++/13009
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 29 Dec 2003 01:30:32 +0000 (01:30 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 29 Dec 2003 01:30:32 +0000 (01:30 +0000)
* call.c (build_special_member_call): Do not assume that we have a
pointer to the complete object in an assignment operator.

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

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@75189 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/assign1.C [new file with mode: 0644]

index 1d96aaf..3f85d7b 100644 (file)
@@ -1,3 +1,9 @@
+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  Roger Sayle  <roger@eyesopen.com>
 
        PR c++/13070
index 2dc4f22..5e75925 100644 (file)
@@ -4865,14 +4865,23 @@ build_special_member_call (tree instance, tree name, tree args,
          || 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.)  */
+      /* Convert to the base class, if necessary.  */
       if (!same_type_ignoring_top_level_qualifiers_p 
          (TREE_TYPE (instance), BINFO_TYPE (binfo)))
-       instance = convert_to_base_statically (instance, 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);
index 6f601e3..0c13a24 100644 (file)
@@ -1,3 +1,8 @@
+2003-12-28  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/13009
+       * g++.dg/init/assign1.C: New test.
+
 2003-12-28  Roger Sayle  <roger@eyesopen.com>
 
        PR c++/13070
diff --git a/gcc/testsuite/g++.dg/init/assign1.C b/gcc/testsuite/g++.dg/init/assign1.C
new file mode 100644 (file)
index 0000000..690a481
--- /dev/null
@@ -0,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;
+}