Author: gclayton
Date: Fri Jul 18 19:12:57 2014
New Revision: 213433

URL: http://llvm.org/viewvc/llvm-project?rev=213433&view=rev
Log:
LLDB now correctly handles virtual inheritance.

Test case added as well.

<rdar://problem/16785904>


Added:
    lldb/trunk/test/lang/cpp/diamond/
    lldb/trunk/test/lang/cpp/diamond/Makefile
    lldb/trunk/test/lang/cpp/diamond/TestDiamond.py
    lldb/trunk/test/lang/cpp/diamond/main.cpp
Modified:
    lldb/trunk/include/lldb/Core/ValueObject.h
    lldb/trunk/include/lldb/Symbol/ClangASTType.h
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Core/ValueObjectConstResultImpl.cpp
    lldb/trunk/source/Symbol/ClangASTType.cpp

Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=213433&r1=213432&r2=213433&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Fri Jul 18 19:12:57 2014
@@ -715,6 +715,10 @@ public:
     {
     }
 
+    // Find the address of the C++ vtable pointer
+    virtual lldb::addr_t
+    GetCPPVTableAddress(AddressType &address_type);
+    
     virtual lldb::ValueObjectSP
     Cast (const ClangASTType &clang_ast_type);
     

Modified: lldb/trunk/include/lldb/Symbol/ClangASTType.h
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTType.h?rev=213433&r1=213432&r2=213433&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTType.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTType.h Fri Jul 18 19:12:57 2014
@@ -426,7 +426,6 @@ public:
     
     ClangASTType
     GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
-                              const char *parent_name,
                               size_t idx,
                               bool transparent_pointers,
                               bool omit_empty_base_classes,
@@ -437,7 +436,8 @@ public:
                               uint32_t &child_bitfield_bit_size,
                               uint32_t &child_bitfield_bit_offset,
                               bool &child_is_base_class,
-                              bool &child_is_deref_of_parent) const;
+                              bool &child_is_deref_of_parent,
+                              ValueObject *valobj) const;
     
     // Lookup a child given a name. This function will match base class names
     // and member member names in "clang_type" only, not descendants.

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=213433&r1=213432&r2=213433&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Fri Jul 18 19:12:57 2014
@@ -793,7 +793,6 @@ ValueObject::CreateChildAtIndex (size_t
     ExecutionContext exe_ctx (GetExecutionContextRef());
     
     child_clang_type = GetClangType().GetChildClangTypeAtIndex (&exe_ctx,
-                                                                
GetName().GetCString(),
                                                                 idx,
                                                                 
transparent_pointers,
                                                                 
omit_empty_base_classes,
@@ -804,7 +803,8 @@ ValueObject::CreateChildAtIndex (size_t
                                                                 
child_bitfield_bit_size,
                                                                 
child_bitfield_bit_offset,
                                                                 
child_is_base_class,
-                                                                
child_is_deref_of_parent);
+                                                                
child_is_deref_of_parent,
+                                                                this);
     if (child_clang_type)
     {
         if (synthetic_index)
@@ -3468,6 +3468,38 @@ ValueObject::CreateConstantValue (const
     return valobj_sp;
 }
 
+lldb::addr_t
+ValueObject::GetCPPVTableAddress (AddressType &address_type)
+{
+    ClangASTType pointee_type;
+    ClangASTType this_type(GetClangType());
+    uint32_t type_info = this_type.GetTypeInfo(&pointee_type);
+    if (type_info)
+    {
+        bool ptr_or_ref = false;
+        if (type_info & (ClangASTType::eTypeIsPointer | 
ClangASTType::eTypeIsReference))
+        {
+            ptr_or_ref = true;
+            type_info = pointee_type.GetTypeInfo();
+        }
+        
+        const uint32_t cpp_class = ClangASTType::eTypeIsClass | 
ClangASTType::eTypeIsCPlusPlus;
+        if ((type_info & cpp_class) == cpp_class)
+        {
+            if (ptr_or_ref)
+            {
+                address_type = GetAddressTypeOfChildren();
+                return GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+            }
+            else
+                return GetAddressOf (false, &address_type);
+        }
+    }
+
+    address_type = eAddressTypeInvalid;
+    return LLDB_INVALID_ADDRESS;
+}
+
 ValueObjectSP
 ValueObject::Dereference (Error &error)
 {
@@ -3494,7 +3526,6 @@ ValueObject::Dereference (Error &error)
         ExecutionContext exe_ctx (GetExecutionContextRef());
         
         child_clang_type = clang_type.GetChildClangTypeAtIndex (&exe_ctx,
-                                                                
GetName().GetCString(),
                                                                 0,
                                                                 
transparent_pointers,
                                                                 
omit_empty_base_classes,
@@ -3505,7 +3536,8 @@ ValueObject::Dereference (Error &error)
                                                                 
child_bitfield_bit_size,
                                                                 
child_bitfield_bit_offset,
                                                                 
child_is_base_class,
-                                                                
child_is_deref_of_parent);
+                                                                
child_is_deref_of_parent,
+                                                                this);
         if (child_clang_type && child_byte_size)
         {
             ConstString child_name;

Modified: lldb/trunk/source/Core/ValueObjectConstResultImpl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectConstResultImpl.cpp?rev=213433&r1=213432&r2=213433&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObjectConstResultImpl.cpp (original)
+++ lldb/trunk/source/Core/ValueObjectConstResultImpl.cpp Fri Jul 18 19:12:57 
2014
@@ -109,7 +109,6 @@ ValueObjectConstResultImpl::CreateChildA
     ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
     
     child_clang_type = clang_type.GetChildClangTypeAtIndex (&exe_ctx,
-                                                            
m_impl_backend->GetName().GetCString(),
                                                             idx,
                                                             
transparent_pointers,
                                                             
omit_empty_base_classes,
@@ -120,7 +119,8 @@ ValueObjectConstResultImpl::CreateChildA
                                                             
child_bitfield_bit_size,
                                                             
child_bitfield_bit_offset,
                                                             
child_is_base_class,
-                                                            
child_is_deref_of_parent);
+                                                            
child_is_deref_of_parent,
+                                                            m_impl_backend);
     if (child_clang_type && child_byte_size)
     {
         if (synthetic_index)

Modified: lldb/trunk/source/Symbol/ClangASTType.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTType.cpp?rev=213433&r1=213432&r2=213433&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTType.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTType.cpp Fri Jul 18 19:12:57 2014
@@ -22,6 +22,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/VTableBuilder.h"
 
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/IdentifierTable.h"
@@ -3068,7 +3069,6 @@ ClangASTType::GetNumPointeeChildren () c
 
 ClangASTType
 ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx,
-                                        const char *parent_name,
                                         size_t idx,
                                         bool transparent_pointers,
                                         bool omit_empty_base_classes,
@@ -3079,7 +3079,8 @@ ClangASTType::GetChildClangTypeAtIndex (
                                         uint32_t &child_bitfield_bit_size,
                                         uint32_t &child_bitfield_bit_offset,
                                         bool &child_is_base_class,
-                                        bool &child_is_deref_of_parent) const
+                                        bool &child_is_deref_of_parent,
+                                        ValueObject *valobj) const
 {
     if (!IsValid())
         return ClangASTType();
@@ -3146,7 +3147,74 @@ ClangASTType::GetChildClangTypeAtIndex (
                             
                             
                             if (base_class->isVirtual())
-                                bit_offset = 
record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
+                            {
+                                bool handled = false;
+                                if (valobj)
+                                {
+                                    Error err;
+                                    AddressType addr_type = 
eAddressTypeInvalid;
+                                    lldb::addr_t vtable_ptr_addr = 
valobj->GetCPPVTableAddress(addr_type);
+                                    
+                                    if (vtable_ptr_addr != 
LLDB_INVALID_ADDRESS && addr_type == eAddressTypeLoad)
+                                    {
+                                        
+                                        ExecutionContext exe_ctx 
(valobj->GetExecutionContextRef());
+                                        Process *process = 
exe_ctx.GetProcessPtr();
+                                        if (process)
+                                        {
+                                            clang::VTableContextBase 
*vtable_ctx = m_ast->getVTableContext();
+                                            if (vtable_ctx)
+                                            {
+                                                if (vtable_ctx->isMicrosoft())
+                                                {
+                                                    
clang::MicrosoftVTableContext *msoft_vtable_ctx = 
static_cast<clang::MicrosoftVTableContext *>(vtable_ctx);
+                                                    
+                                                    if (vtable_ptr_addr)
+                                                    {
+                                                        const lldb::addr_t 
vbtable_ptr_addr = vtable_ptr_addr + 
record_layout.getVBPtrOffset().getQuantity();
+                                                        
+                                                        const lldb::addr_t 
vbtable_ptr = process->ReadPointerFromMemory(vbtable_ptr_addr, err);
+                                                        if (vbtable_ptr != 
LLDB_INVALID_ADDRESS)
+                                                        {
+                                                            // Get the index 
into the virtual base table. The index is the index in uint32_t from vbtable_ptr
+                                                            const unsigned 
vbtable_index = msoft_vtable_ctx->getVBTableIndex(cxx_record_decl, 
base_class_decl);
+                                                            const lldb::addr_t 
base_offset_addr = vbtable_ptr + vbtable_index * 4;
+                                                            const uint32_t 
base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, 
UINT32_MAX, err);
+                                                            if (base_offset != 
UINT32_MAX)
+                                                            {
+                                                                handled = true;
+                                                                bit_offset = 
base_offset * 8;
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                                else
+                                                {
+                                                    
clang::ItaniumVTableContext *itanium_vtable_ctx = 
static_cast<clang::ItaniumVTableContext *>(vtable_ctx);
+                                                    if (vtable_ptr_addr)
+                                                    {
+                                                        const lldb::addr_t 
vtable_ptr = process->ReadPointerFromMemory(vtable_ptr_addr, err);
+                                                        if (vtable_ptr != 
LLDB_INVALID_ADDRESS)
+                                                        {
+                                                            clang::CharUnits 
base_offset_offset = 
itanium_vtable_ctx->getVirtualBaseOffsetOffset(cxx_record_decl, 
base_class_decl);
+                                                            const lldb::addr_t 
base_offset_addr = vtable_ptr + base_offset_offset.getQuantity();
+                                                            const uint32_t 
base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, 
UINT32_MAX, err);
+                                                            if (base_offset != 
UINT32_MAX)
+                                                            {
+                                                                handled = true;
+                                                                bit_offset = 
base_offset * 8;
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+
+                                }
+                                if (!handled)
+                                    bit_offset = 
record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
+                            }
                             else
                                 bit_offset = 
record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8;
                             
@@ -3321,7 +3389,6 @@ ClangASTType::GetChildClangTypeAtIndex (
                     child_is_deref_of_parent = false;
                     bool tmp_child_is_deref_of_parent = false;
                     return pointee_clang_type.GetChildClangTypeAtIndex 
(exe_ctx,
-                                                                        
parent_name,
                                                                         idx,
                                                                         
transparent_pointers,
                                                                         
omit_empty_base_classes,
@@ -3332,11 +3399,13 @@ ClangASTType::GetChildClangTypeAtIndex (
                                                                         
child_bitfield_bit_size,
                                                                         
child_bitfield_bit_offset,
                                                                         
child_is_base_class,
-                                                                        
tmp_child_is_deref_of_parent);
+                                                                        
tmp_child_is_deref_of_parent,
+                                                                        
valobj);
                 }
                 else
                 {
                     child_is_deref_of_parent = true;
+                    const char *parent_name = valobj ? 
valobj->GetName().GetCString() : NULL;
                     if (parent_name)
                     {
                         child_name.assign(1, '*');
@@ -3411,7 +3480,6 @@ ClangASTType::GetChildClangTypeAtIndex (
                     child_is_deref_of_parent = false;
                     bool tmp_child_is_deref_of_parent = false;
                     return pointee_clang_type.GetChildClangTypeAtIndex 
(exe_ctx,
-                                                                        
parent_name,
                                                                         idx,
                                                                         
transparent_pointers,
                                                                         
omit_empty_base_classes,
@@ -3422,12 +3490,14 @@ ClangASTType::GetChildClangTypeAtIndex (
                                                                         
child_bitfield_bit_size,
                                                                         
child_bitfield_bit_offset,
                                                                         
child_is_base_class,
-                                                                        
tmp_child_is_deref_of_parent);
+                                                                        
tmp_child_is_deref_of_parent,
+                                                                        
valobj);
                 }
                 else
                 {
                     child_is_deref_of_parent = true;
                     
+                    const char *parent_name = valobj ? 
valobj->GetName().GetCString() : NULL;
                     if (parent_name)
                     {
                         child_name.assign(1, '*');
@@ -3456,7 +3526,6 @@ ClangASTType::GetChildClangTypeAtIndex (
                     child_is_deref_of_parent = false;
                     bool tmp_child_is_deref_of_parent = false;
                     return pointee_clang_type.GetChildClangTypeAtIndex 
(exe_ctx,
-                                                                        
parent_name,
                                                                         idx,
                                                                         
transparent_pointers,
                                                                         
omit_empty_base_classes,
@@ -3467,10 +3536,12 @@ ClangASTType::GetChildClangTypeAtIndex (
                                                                         
child_bitfield_bit_size,
                                                                         
child_bitfield_bit_offset,
                                                                         
child_is_base_class,
-                                                                        
tmp_child_is_deref_of_parent);
+                                                                        
tmp_child_is_deref_of_parent,
+                                                                        
valobj);
                 }
                 else
                 {
+                    const char *parent_name = valobj ? 
valobj->GetName().GetCString() : NULL;
                     if (parent_name)
                     {
                         child_name.assign(1, '&');
@@ -3492,7 +3563,6 @@ ClangASTType::GetChildClangTypeAtIndex (
             {
                 ClangASTType typedefed_clang_type (m_ast, 
llvm::cast<clang::TypedefType>(parent_qual_type)->getDecl()->getUnderlyingType());
                 return typedefed_clang_type.GetChildClangTypeAtIndex (exe_ctx,
-                                                                      
parent_name,
                                                                       idx,
                                                                       
transparent_pointers,
                                                                       
omit_empty_base_classes,
@@ -3503,7 +3573,8 @@ ClangASTType::GetChildClangTypeAtIndex (
                                                                       
child_bitfield_bit_size,
                                                                       
child_bitfield_bit_offset,
                                                                       
child_is_base_class,
-                                                                      
child_is_deref_of_parent);
+                                                                      
child_is_deref_of_parent,
+                                                                      valobj);
             }
             break;
             
@@ -3511,7 +3582,6 @@ ClangASTType::GetChildClangTypeAtIndex (
             {
                 ClangASTType elaborated_clang_type (m_ast, 
llvm::cast<clang::ElaboratedType>(parent_qual_type)->getNamedType());
                 return elaborated_clang_type.GetChildClangTypeAtIndex (exe_ctx,
-                                                                       
parent_name,
                                                                        idx,
                                                                        
transparent_pointers,
                                                                        
omit_empty_base_classes,
@@ -3522,14 +3592,14 @@ ClangASTType::GetChildClangTypeAtIndex (
                                                                        
child_bitfield_bit_size,
                                                                        
child_bitfield_bit_offset,
                                                                        
child_is_base_class,
-                                                                       
child_is_deref_of_parent);
+                                                                       
child_is_deref_of_parent,
+                                                                       valobj);
             }
             
         case clang::Type::Paren:
             {
                 ClangASTType paren_clang_type (m_ast, 
llvm::cast<clang::ParenType>(parent_qual_type)->desugar());
                 return paren_clang_type.GetChildClangTypeAtIndex (exe_ctx,
-                                                                  parent_name,
                                                                   idx,
                                                                   
transparent_pointers,
                                                                   
omit_empty_base_classes,
@@ -3540,7 +3610,8 @@ ClangASTType::GetChildClangTypeAtIndex (
                                                                   
child_bitfield_bit_size,
                                                                   
child_bitfield_bit_offset,
                                                                   
child_is_base_class,
-                                                                  
child_is_deref_of_parent);
+                                                                  
child_is_deref_of_parent,
+                                                                  valobj);
             }
             
             

Added: lldb/trunk/test/lang/cpp/diamond/Makefile
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/diamond/Makefile?rev=213433&view=auto
==============================================================================
--- lldb/trunk/test/lang/cpp/diamond/Makefile (added)
+++ lldb/trunk/test/lang/cpp/diamond/Makefile Fri Jul 18 19:12:57 2014
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/lang/cpp/diamond/TestDiamond.py
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/diamond/TestDiamond.py?rev=213433&view=auto
==============================================================================
--- lldb/trunk/test/lang/cpp/diamond/TestDiamond.py (added)
+++ lldb/trunk/test/lang/cpp/diamond/TestDiamond.py Fri Jul 18 19:12:57 2014
@@ -0,0 +1,63 @@
+"""
+Tests that bool types work
+"""
+import lldb
+from lldbtest import *
+import lldbutil
+
+class CPPTestDiamondInheritance(TestBase):
+    
+    mydir = TestBase.compute_mydir(__file__)
+    
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @dsym_test
+    def test_with_dsym_and_run_command(self):
+        """Test that virtual base classes work in when SBValue objects are 
used to explore the variable value"""
+        self.buildDsym()
+        self.diamong_inheritace()
+
+    @dwarf_test
+    def test_with_dwarf_and_run_command(self):
+        """Test that virtual base classes work in when SBValue objects are 
used to explore the variable value"""
+        self.buildDwarf()
+        self.diamong_inheritace()
+
+    def setUp(self):
+        TestBase.setUp(self)
+    
+    def set_breakpoint(self, line):
+        # Some compilers (for example GCC 4.4.7 and 4.6.1) emit multiple 
locations for the statement with the ternary
+        # operator in the test program, while others emit only 1.
+        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", line, 
num_expected_locations=-1, loc_exact=False)
+
+    def diamong_inheritace(self):
+        """Test that virtual base classes work in when SBValue objects are 
used to explore the variable value"""
+        
+        exe = os.path.join(os.getcwd(), "a.out")
+        
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+        self.set_breakpoint(line_number('main.cpp', '// breakpoint 1'))
+        self.set_breakpoint(line_number('main.cpp', '// breakpoint 2'))
+        process = target.LaunchSimple (None, None, 
self.get_process_working_directory())
+        self.assertTrue(process, PROCESS_IS_VALID)
+        thread = process.GetThreadAtIndex(0)
+        frame = thread.GetFrameAtIndex(0)
+        j1 = frame.FindVariable("j1")
+        j1_Derived1 = j1.GetChildAtIndex(0)
+        j1_Derived2 = j1.GetChildAtIndex(1)
+        j1_Derived1_VBase = j1_Derived1.GetChildAtIndex(0)
+        j1_Derived2_VBase = j1_Derived2.GetChildAtIndex(0)
+        j1_Derived1_VBase_m_value = j1_Derived1_VBase.GetChildAtIndex(0)
+        j1_Derived2_VBase_m_value = j1_Derived2_VBase.GetChildAtIndex(0)
+        self.assertTrue(j1_Derived1_VBase.GetLoadAddress() == 
j1_Derived2_VBase.GetLoadAddress(), "ensure virtual base class is the same 
between Derived1 and Derived2")
+        self.assertTrue(j1_Derived1_VBase_m_value.GetValueAsUnsigned(1) == 
j1_Derived2_VBase_m_value.GetValueAsUnsigned(2), "ensure m_value in VBase is 
the same")
+        
self.assertTrue(frame.FindVariable("d").GetChildAtIndex(0).GetChildAtIndex(0).GetValueAsUnsigned(0)
 == 12345, "ensure Derived2 from j1 is correct");
+        thread.StepOver()
+        
self.assertTrue(frame.FindVariable("d").GetChildAtIndex(0).GetChildAtIndex(0).GetValueAsUnsigned(0)
 == 12346, "ensure Derived2 from j2 is correct");
+        
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/lang/cpp/diamond/main.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/diamond/main.cpp?rev=213433&view=auto
==============================================================================
--- lldb/trunk/test/lang/cpp/diamond/main.cpp (added)
+++ lldb/trunk/test/lang/cpp/diamond/main.cpp Fri Jul 18 19:12:57 2014
@@ -0,0 +1,85 @@
+//===-- main.cpp ------------------------------------------------*- C++ 
-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <stdio.h>
+
+static int g_next_value = 12345;
+
+class VBase
+{
+public:
+    VBase() : m_value(g_next_value++) {}
+    virtual ~VBase() {}
+    void Print() 
+    {
+        printf("%p: %s\n%p: m_value = 0x%8.8x\n", this, __PRETTY_FUNCTION__, 
&m_value, m_value);
+    }
+    int m_value;
+};
+
+class Derived1 : public virtual VBase
+{
+public:
+    Derived1() {};
+    void Print ()
+    {
+        printf("%p: %s\n", this, __PRETTY_FUNCTION__);
+        VBase::Print();
+    }
+
+};
+
+class Derived2 : public virtual VBase
+{
+public:
+    Derived2() {};
+    
+    void Print ()
+    {
+        printf("%p: %s\n", this, __PRETTY_FUNCTION__);
+        VBase::Print();
+    }
+};
+
+class Joiner1 : public Derived1, public Derived2
+{
+public:
+    Joiner1() : 
+        m_joiner1(3456), 
+        m_joiner2(6789) {}
+    void Print ()
+    {
+        printf("%p: %s \n%p: m_joiner1 = 0x%8.8x\n%p: m_joiner2 = 0x%8.8x\n",
+               this,
+               __PRETTY_FUNCTION__,
+               &m_joiner1,
+               m_joiner1,
+               &m_joiner2,
+               m_joiner2);
+        Derived1::Print();
+        Derived2::Print();
+    }
+    int m_joiner1;
+    int m_joiner2;
+};
+
+class Joiner2 : public Derived2
+{
+    int m_stuff[32];
+};
+
+int main(int argc, const char * argv[])
+{
+    Joiner1 j1;
+    Joiner2 j2;
+    j1.Print();
+    j2.Print();
+    Derived2 *d = &j1;
+    d = &j2;  // breakpoint 1
+    return 0; // breakpoint 2
+}


_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to