diff options
author | Mark Mitchell <mark@codesourcery.com> | 2003-12-29 01:30:32 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2003-12-29 01:30:32 +0000 |
commit | 4c2a4b907dc3d79259747b6f21b1633d8e4c99aa (patch) | |
tree | 95eb9b436bb199f883158f9eaef78ea125c612bb | |
parent | 6c5d63c80bb05f372f695a37e96b9a409793fed3 (diff) | |
download | gcc-4c2a4b907dc3d79259747b6f21b1633d8e4c99aa.zip gcc-4c2a4b907dc3d79259747b6f21b1633d8e4c99aa.tar.gz gcc-4c2a4b907dc3d79259747b6f21b1633d8e4c99aa.tar.bz2 |
re PR c++/13009 (Implicitly-defined assignment operator writes to wrong memory)
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.
PR c++/13009
* g++.dg/init/assign1.C: New test.
From-SVN: r75189
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/call.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/assign1.C | 30 |
4 files changed, 56 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1d96aaf..3f85d7b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 2dc4f22..5e75925 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6f601e3..0c13a24 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..690a481 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/assign1.C @@ -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; +} |