[cfe-commits] [libcxxabi] r148038 - in /libcxxabi/trunk: src/private_typeinfo.cpp test/dynamic_cast3.cpp
Howard Hinnant
hhinnant at apple.com
Thu Jan 12 11:48:14 PST 2012
Author: hhinnant
Date: Thu Jan 12 13:48:14 2012
New Revision: 148038
URL: http://llvm.org/viewvc/llvm-project?rev=148038&view=rev
Log:
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.
Added:
libcxxabi/trunk/test/dynamic_cast3.cpp
Modified:
libcxxabi/trunk/src/private_typeinfo.cpp
Modified: libcxxabi/trunk/src/private_typeinfo.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/private_typeinfo.cpp?rev=148038&r1=148037&r2=148038&view=diff
==============================================================================
--- libcxxabi/trunk/src/private_typeinfo.cpp (original)
+++ libcxxabi/trunk/src/private_typeinfo.cpp Thu Jan 12 13:48:14 2012
@@ -62,6 +62,11 @@
// __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 @@
// 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 @@
// 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 @@
// 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::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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
// (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 @@
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;
}
Added: libcxxabi/trunk/test/dynamic_cast3.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/dynamic_cast3.cpp?rev=148038&view=auto
==============================================================================
--- libcxxabi/trunk/test/dynamic_cast3.cpp (added)
+++ libcxxabi/trunk/test/dynamic_cast3.cpp Thu Jan 12 13:48:14 2012
@@ -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();
+}
More information about the cfe-commits
mailing list