diff options
| author | Howard Hinnant <hhinnant@apple.com> | 2012-01-12 19:48:14 +0000 |
|---|---|---|
| committer | Howard Hinnant <hhinnant@apple.com> | 2012-01-12 19:48:14 +0000 |
| commit | af07bfdb67b53b4db7b9766ea7928fd53ec8aa3c (patch) | |
| tree | a6cda95110cd559a0d77f3c94e406b4ff540f32f | |
| parent | b02c5e9356a1b7176d86ee54b521b5a05daacbb3 (diff) | |
| download | bcm5719-llvm-af07bfdb67b53b4db7b9766ea7928fd53ec8aa3c.tar.gz bcm5719-llvm-af07bfdb67b53b4db7b9766ea7928fd53ec8aa3c.zip | |
Fixed a couple of bugs, updated many comments, and am including a comprehensive test for when there are only 3 types in place. I need to do something similar for 4 and maybe more types, but I'm not sure how comprehensive I can make the test at 4 and above types.
llvm-svn: 148038
| -rw-r--r-- | libcxxabi/src/private_typeinfo.cpp | 159 | ||||
| -rw-r--r-- | libcxxabi/test/dynamic_cast3.cpp | 2453 |
2 files changed, 2565 insertions, 47 deletions
diff --git a/libcxxabi/src/private_typeinfo.cpp b/libcxxabi/src/private_typeinfo.cpp index 04dc3ac2d4d..4f0b5bb664a 100644 --- a/libcxxabi/src/private_typeinfo.cpp +++ b/libcxxabi/src/private_typeinfo.cpp @@ -62,6 +62,11 @@ __class_type_info::~__class_type_info() // __dynamic_cast notes: // Up or above refers to base classes and base objects. // Down or below refers to derived classes/objects. +// There are two search algorithms, search1 and search2. +// search1 is nothing but an optimization of search2 for a special case. +// Take it away and things should still work correctly. +// Both algorithms return 1 if the search should continue below the current node +// and 0 if the search should be aborted (because the answer is now known). // search1 is a search algorithm used by __dynamic_cast. // If a static_type is found @@ -73,35 +78,13 @@ __class_type_info::~__class_type_info() // Else // Continue search above and below this node. -// __class_type_info::search1 -// There are no nodes to search above this node -// Returns: 1 if search should be continued, otherwise 0 -int -__class_type_info::search1(__dynamic_cast_info* info, const void* dynamic_ptr, - int path_below) const -{ - if (this == info->static_type) - { - if (dynamic_ptr == info->static_ptr) - { - if (path_below == public_path) - { - info->path_dynamic_ptr_to_static_ptr = public_path; - return 0; - } - info->path_dynamic_ptr_to_static_ptr = not_public_path; - } - } - return 1; -} - // search2 is a search algorithm used by __dynamic_cast. // if this is a dst_type -// if this has already been classified then +// if this node has already been classified then // If the path to get here is public, overwrite existing path_dynamic_ptr_to_dst_ptr. -// else we haven't been to this dst_type before. +// else we haven't been to this (ptr, dst_type) before. // Record the path to get here in path_dynamic_ptr_to_dst_ptr. -// Is (static_ptr, static_type) above this dst_type? +// For each base is (static_ptr, static_type) above this dst_type? // Yes: // Record it as dst_ptr_leading_to_static_ptr and increment the // number of such recordings. @@ -110,6 +93,7 @@ __class_type_info::search1(__dynamic_cast_info* info, const void* dynamic_ptr, // No: // record it as dst_ptr_not_leading_to_static_ptr and increment // the number of such recordings. +// Continue searching both above and below this node. // else if this is a static_type // if this is *our* static_type // if we found it above a dst_type, record the path from the dst_type @@ -119,6 +103,30 @@ __class_type_info::search1(__dynamic_cast_info* info, const void* dynamic_ptr, // Continue searching only below this node // else // Continue searching above and below this node. + +// __class_type_info::search1 +// There are no nodes to search above this node +int +__class_type_info::search1(__dynamic_cast_info* info, const void* dynamic_ptr, + int path_below) const +{ + if (this == info->static_type) + { + if (dynamic_ptr == info->static_ptr) + { + if (path_below == public_path) + { + info->path_dynamic_ptr_to_static_ptr = public_path; + return 0; + } + info->path_dynamic_ptr_to_static_ptr = not_public_path; + } + } + return 1; +} + +// __class_type_info::search2 +// There are no nodes to search above this node int __class_type_info::search2(__dynamic_cast_info* info, const void* dynamic_ptr, int path_below) const @@ -160,6 +168,9 @@ __si_class_type_info::~__si_class_type_info() { } +// __si_class_type_info::search1 +// There is one node to search above this node. The path to it is public +// and dynamic_ptr needs no adjustment in moving to that node. int __si_class_type_info::search1(__dynamic_cast_info* info, const void* dynamic_ptr, int path_below) const @@ -179,6 +190,9 @@ __si_class_type_info::search1(__dynamic_cast_info* info, const void* dynamic_ptr return __base_type->search1(info, dynamic_ptr, path_below); } +// __si_class_type_info::search2 +// There is one node to search above this node. The path to it is public +// and dynamic_ptr needs no adjustment in moving to that node. int __si_class_type_info::search2(__dynamic_cast_info* info, const void* dynamic_ptr, int path_below) const @@ -237,6 +251,11 @@ __vmi_class_type_info::~__vmi_class_type_info() { } +// __vmi_class_type_info::search1 +// There are one or more nodes to search above this node. The path to it +// may be public or not and the dynamic_ptr may need to be adjusted. Both +// of these details are handled by a pseudo-node in __base_class_type_info +// which has no type associated with it. int __vmi_class_type_info::search1(__dynamic_cast_info* info, const void* dynamic_ptr, int path_below) const @@ -263,21 +282,11 @@ __vmi_class_type_info::search1(__dynamic_cast_info* info, const void* dynamic_pt return 1; } -int -__base_class_type_info::search1(__dynamic_cast_info* info, const void* dynamic_ptr, - int path_below) const -{ - ptrdiff_t offset_to_base = __offset_flags >> __offset_shift; - if (__offset_flags & __virtual_mask) - { - char* vtable = *(char**)dynamic_ptr; - offset_to_base = (ptrdiff_t)vtable[offset_to_base]; - } - return __base_type->search1(info, (char*)dynamic_ptr + offset_to_base, - (__offset_flags & __public_mask) ? path_below : - not_public_path); -} - +// __vmi_class_type_info::search2 +// There are one or more nodes to search above this node. The path to it +// may be public or not and the dynamic_ptr may need to be adjusted. Both +// of these details are handled by a pseudo-node in __base_class_type_info +// which has no type associated with it. int __vmi_class_type_info::search2(__dynamic_cast_info* info, const void* dynamic_ptr, int path_below) const @@ -297,10 +306,10 @@ __vmi_class_type_info::search2(__dynamic_cast_info* info, const void* dynamic_pt for (Iter p = __base_info, e = __base_info + __base_count; p < e; ++p) { info->above_dst_ptr = true; - int r = p->search2(info, dynamic_ptr, public_path); + // Only a dst_type can abort the search, and one can't be + // above here. So it is safe to ignore return. + (void)p->search2(info, dynamic_ptr, public_path); info->above_dst_ptr = false; - if (r == 0) - return 0; if (info->found_static_ptr) { info->found_static_ptr = false; @@ -339,6 +348,35 @@ __vmi_class_type_info::search2(__dynamic_cast_info* info, const void* dynamic_pt return 1; } +// __base_class_type_info::search1 +// This is a psuedo-node which does nothing but adjust the path access and +// dynamic_ptr prior to calling the base node above. +// The dynamic_ptr adjustment depends upon whether or not this node is marked +// virtual. +// If the path up is public, no change is made to the path (it may already be +// marked private from below). If the path up is private, it is forced so. +int +__base_class_type_info::search1(__dynamic_cast_info* info, const void* dynamic_ptr, + int path_below) const +{ + ptrdiff_t offset_to_base = __offset_flags >> __offset_shift; + if (__offset_flags & __virtual_mask) + { + char* vtable = *(char**)dynamic_ptr; + offset_to_base = *(ptrdiff_t*)(vtable + offset_to_base); + } + return __base_type->search1(info, (char*)dynamic_ptr + offset_to_base, + (__offset_flags & __public_mask) ? path_below : + not_public_path); +} + +// __base_class_type_info::search2 +// This is a psuedo-node which does nothing but adjust the path access and +// dynamic_ptr prior to calling the base node above. +// The dynamic_ptr adjustment depends upon whether or not this node is marked +// virtual. +// If the path up is public, no change is made to the path (it may already be +// marked private from below). If the path up is private, it is forced so. int __base_class_type_info::search2(__dynamic_cast_info* info, const void* dynamic_ptr, int path_below) const @@ -347,7 +385,7 @@ __base_class_type_info::search2(__dynamic_cast_info* info, const void* dynamic_p if (__offset_flags & __virtual_mask) { char* vtable = *(char**)dynamic_ptr; - offset_to_base = (ptrdiff_t)vtable[offset_to_base]; + offset_to_base = *(ptrdiff_t*)(vtable + offset_to_base); } return __base_type->search2(info, (char*)dynamic_ptr + offset_to_base, (__offset_flags & __public_mask) ? path_below : @@ -378,7 +416,7 @@ __base_class_type_info::display(const void* obj) const if (__offset_flags & __virtual_mask) { char* vtable = *(char**)obj; - offset_to_base = (ptrdiff_t)vtable[offset_to_base]; + offset_to_base = *(ptrdiff_t*)(vtable + offset_to_base); } __base_type->display((char*)obj + offset_to_base); } @@ -426,7 +464,7 @@ __pointer_to_member_type_info::~__pointer_to_member_type_info() // ambiguity, or // 3. nullptr // Knowns: -// (dynamic_ptr, dynamic_type) can be derived from static_ptr. +// (dynamic_ptr, dynamic_type) can be extracted from static_ptr. // dynamic_ptr is a pointer to the complete run time object. // dynamic_type is the type of the complete run time object. // The type hierarchy is a DAG rooted at (dynamic_ptr, dynamic_type) and @@ -448,6 +486,27 @@ __pointer_to_member_type_info::~__pointer_to_member_type_info() // (dynamic_ptr, dynamic_type) to (static_ptr, static_type), // else returns nullptr. // This check is purely an optimization and does not impact correctness. +// Algorithm: +// Extract (dynamic_ptr, dynamic_type) from static_ptr. +// If dynamic_type == dst_type +// If there is a public path from (dynamic_ptr, dynamic_type) to +// (static_ptr, static_type), return dynamic_ptr else return nullptr. +// Else dynamic_type != dst_type +// If there is a single dst_type derived (below) (static_ptr, static_type) +// If the path from that unique dst_type to (static_ptr, static_type) +// is public, return a pointer to that dst_type else return nullptr. +// Else if there are no dst_type's which don't point to (static_ptr, static_type) +// and if there is a pubic path from (dynamic_ptr, dynamic_type) to +// (static_ptr, static_type) and a public path from (dynamic_ptr, dynamic_type) +// to the single dst_type, then return a pointer to that dst_type, +// Else return nullptr. +// Else if there are no dst_type derived (below) (static_ptr, static_type) +// And if there is a single dst_type base of (above) +// (dynamic_ptr, dynamic_type), and if that single dst_type has a +// public path to it. And if there is a public path +// from (dynamic_ptr, dynamic_type) to (static_ptr, static_type) +// then return a pointer to that single dst_type, else return nullptr. +// Else return nullptr. extern "C" void* __dynamic_cast(const void* static_ptr, @@ -487,7 +546,13 @@ dynamic_type->display(dynamic_ptr); dst_ptr = info.dst_ptr_not_leading_to_static_ptr; break; case 1: - if (info.path_dst_ptr_to_static_ptr == public_path) + if (info.path_dst_ptr_to_static_ptr == public_path || + ( + info.number_to_dst_ptr == 0 && + info.path_dynamic_ptr_to_static_ptr == public_path && + info.path_dynamic_ptr_to_dst_ptr == public_path + ) + ) dst_ptr = info.dst_ptr_leading_to_static_ptr; break; } diff --git a/libcxxabi/test/dynamic_cast3.cpp b/libcxxabi/test/dynamic_cast3.cpp new file mode 100644 index 00000000000..2f2cf93fec0 --- /dev/null +++ b/libcxxabi/test/dynamic_cast3.cpp @@ -0,0 +1,2453 @@ +//===------------------------- dynamic_cast3.cpp --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <iostream> +#include <cassert> + +/* + +A1 A2 A3 + +*/ + +namespace t1 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA3()) == 0); + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == 0); + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t1 + +/* + +A1 A2 +| +A3 + +*/ + +namespace t2 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : public A1 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA3()) == 0); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t2 + +namespace t3 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : public virtual A1 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA3()) == 0); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t3 + +namespace t4 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : private A1 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA3()) == 0); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t4 + +namespace t5 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : private virtual A1 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA3()) == 0); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t5 + +/* + +A1 A2 + \ / + A3 + +*/ + +namespace t6 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : public A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t6 + +namespace t7 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : public virtual A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t7 + +namespace t8 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : private A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == 0); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t8 + +namespace t9 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : private virtual A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == 0); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t9 + +namespace t10 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : public virtual A1, + public virtual A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t10 + +namespace t11 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : private A1, + public virtual A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == 0); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t11 + +namespace t12 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : private virtual A1, + public virtual A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == 0); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t12 + +namespace t13 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : private A1, + private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == 0); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t13 + +namespace t14 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : private virtual A1, + private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == 0); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t14 + +namespace t15 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A2* getA2() {return this;} +}; + +struct A3 + : private virtual A1, + private virtual A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == 0); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == 0); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t15 + +/* + +A1 +| +A2 +| +A3 + +*/ + +namespace t16 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : public A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == a2.getA2()); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t16 + +namespace t17 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : public virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == a2.getA2()); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t17 + +namespace t18 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t18 + +namespace t19 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t19 + +namespace t20 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : public virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public virtual A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == a2.getA2()); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t20 + +namespace t21 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public virtual A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t21 + +namespace t22 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public virtual A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t22 + +namespace t23 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + t23::A1* getA1() {return A2::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t23 + +namespace t24 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + t24::A1* getA1() {return A2::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t24 + +namespace t25 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : private virtual A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + t25::A1* getA1() {return A2::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t25 + +/* + +A1 A1 +| | +A2 | + \ | + A3 + +*/ + +namespace t26 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : public A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA12() {return A2::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA12()) == a3.getA12()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA12()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == a2.getA2()); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA12()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA12()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t26 + +namespace t27 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA12() {return A2::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA12()) == a3.getA12()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA12()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA12()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t27 + +namespace t28 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : public A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : private A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA12() {return A2::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA12()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == a2.getA2()); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA12()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA12()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t28 + +namespace t29 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : public A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public A1, + private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA12() {return A2::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA12()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == a2.getA2()); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA12()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA12()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t29 + +namespace t30 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : public A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : private A1, + private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA12() {return A2::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA12()) == a3.getA12()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA12()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == a2.getA2()); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA12()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA12()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t30 + +namespace t31 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public A1, + private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA12() {return A2::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA12()) == a3.getA12()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA12()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA12()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t31 + +namespace t32 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : private A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA12() {return A2::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA12()) == a3.getA12()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA12()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA12()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t32 + +namespace t33 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : private A1, + private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA12() {return A2::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA12()) == a3.getA12()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA12()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA12()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t33 + +/* + +A1 +| \ +A2 \ + \ | + A3 + +*/ + +namespace t34 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : public virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public virtual A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return A1::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == a2.getA2()); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t34 + +namespace t35 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public virtual A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return A1::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t35 + +namespace t36 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : public virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : private virtual A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return A1::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == a2.getA2()); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t36 + +namespace t37 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : public virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public virtual A1, + private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return A1::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == a2.getA2()); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t37 + +namespace t38 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : public virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : private virtual A1, + private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return A1::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a2.getA2()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA2()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == a2.getA2()); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t38 + +namespace t39 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : public virtual A1, + private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return A1::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + assert(dynamic_cast<A1*>(a3.getA3()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t39 + +namespace t40 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : private virtual A1, + public A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return A1::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + assert(dynamic_cast<A2*>(a3.getA3()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == a3.getA3()); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t40 + +namespace t41 +{ + +struct A1 +{ + char _[43981]; + virtual ~A1() {std::cout << this << " ~A1()\n";} + + A1* getA1() {return this;} +}; + +struct A2 + : private virtual A1 +{ + char _[34981]; + virtual ~A2() {std::cout << this << " ~A2()\n";} + + A1* getA1() {return this;} + A2* getA2() {return this;} +}; + +struct A3 + : private virtual A1, + private A2 +{ + char _[93481]; + virtual ~A3() {std::cout << this << " ~A3()\n";} + + A1* getA1() {return A1::getA1();} + A2* getA2() {return this;} + A3* getA3() {return this;} +}; + +void test() +{ + A1 a1; + A2 a2; + A3 a3; + assert(dynamic_cast<A1*>(a1.getA1()) == a1.getA1()); + assert(dynamic_cast<A1*>(a2.getA1()) == a2.getA1()); + assert(dynamic_cast<A1*>(a3.getA1()) == a3.getA1()); + + assert(dynamic_cast<A2*>(a1.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA1()) == 0); + assert(dynamic_cast<A2*>(a2.getA2()) == a2.getA2()); + assert(dynamic_cast<A2*>(a3.getA1()) == 0); + assert(dynamic_cast<A2*>(a3.getA2()) == a3.getA2()); + + assert(dynamic_cast<A3*>(a1.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA1()) == 0); + assert(dynamic_cast<A3*>(a2.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA1()) == 0); + assert(dynamic_cast<A3*>(a3.getA2()) == 0); + assert(dynamic_cast<A3*>(a3.getA3()) == a3.getA3()); +} + +} // t41 + +int main() +{ + t1::test(); + t2::test(); + t3::test(); + t4::test(); + t5::test(); + t6::test(); + t7::test(); + t8::test(); + t9::test(); + t10::test(); + t11::test(); + t12::test(); + t13::test(); + t14::test(); + t15::test(); + t16::test(); + t17::test(); + t18::test(); + t19::test(); + t20::test(); + t21::test(); + t22::test(); + t23::test(); + t24::test(); + t25::test(); + t26::test(); + t27::test(); + t28::test(); + t29::test(); + t30::test(); + t31::test(); + t32::test(); + t33::test(); + t34::test(); + t35::test(); + t36::test(); + t37::test(); + t38::test(); + t39::test(); + t40::test(); + t41::test(); +} |

