[Lldb-commits] [lldb] r169465 - in /lldb/trunk: include/lldb/Symbol/ClangASTContext.h source/Core/Debugger.cpp source/Core/Value.cpp source/Core/ValueObject.cpp source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp source/Symbol/ClangASTContext.cpp source/Symbol/ClangASTType.cpp source/Target/StackFrame.cpp test/lang/c/struct_types/TestStructTypes.py test/lang/c/struct_types/main.c

Greg Clayton gclayton at apple.com
Wed Dec 5 18:33:54 PST 2012


Author: gclayton
Date: Wed Dec  5 20:33:54 2012
New Revision: 169465

URL: http://llvm.org/viewvc/llvm-project?rev=169465&view=rev
Log:
<rdar://problem/12560257>

Fixed zero sized arrays to work correctly. This will only happen once we get a clang that emits correct debug info for zero sized arrays. For now I have marked the TestStructTypes.py as an expected failure.


Modified:
    lldb/trunk/include/lldb/Symbol/ClangASTContext.h
    lldb/trunk/source/Core/Debugger.cpp
    lldb/trunk/source/Core/Value.cpp
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/trunk/source/Symbol/ClangASTContext.cpp
    lldb/trunk/source/Symbol/ClangASTType.cpp
    lldb/trunk/source/Target/StackFrame.cpp
    lldb/trunk/test/lang/c/struct_types/TestStructTypes.py
    lldb/trunk/test/lang/c/struct_types/main.c

Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=169465&r1=169464&r2=169465&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Wed Dec  5 20:33:54 2012
@@ -785,9 +785,8 @@
     //------------------------------------------------------------------
 
     lldb::clang_type_t
-    CreateArrayType (lldb::clang_type_t  element_type,
-                     size_t element_count,
-                     uint32_t bit_stride);
+    CreateArrayType (lldb::clang_type_t element_type,
+                     size_t element_count);
 
     //------------------------------------------------------------------
     // Tag Declarations
@@ -887,15 +886,17 @@
     
     static lldb::clang_type_t
     GetAsArrayType (lldb::clang_type_t clang_type, 
-                    lldb::clang_type_t *member_type = NULL, 
-                    uint64_t *size = NULL);
+                    lldb::clang_type_t *member_type,
+                    uint64_t *size,
+                    bool *is_incomplete);
     
     static bool
     IsArrayType (lldb::clang_type_t clang_type,
-                 lldb::clang_type_t *member_type = NULL,
-                 uint64_t *size = NULL)
+                 lldb::clang_type_t *member_type,
+                 uint64_t *size,
+                 bool *is_incomplete)
     {
-        return GetAsArrayType(clang_type, member_type, size) != 0;
+        return GetAsArrayType(clang_type, member_type, size, is_incomplete) != 0;
     }
 
     //------------------------------------------------------------------

Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=169465&r1=169464&r2=169465&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Wed Dec  5 20:33:54 2012
@@ -1551,7 +1551,7 @@
                                 }
                                 
                                 // TODO use flags for these
-                                bool is_array = ClangASTContext::IsArrayType(target->GetClangType());
+                                bool is_array = ClangASTContext::IsArrayType(target->GetClangType(), NULL, NULL, NULL);
                                 bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType());
                                 bool is_aggregate = ClangASTContext::IsAggregateType(target->GetClangType());
                                 

Modified: lldb/trunk/source/Core/Value.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Value.cpp?rev=169465&r1=169464&r2=169465&view=diff
==============================================================================
--- lldb/trunk/source/Core/Value.cpp (original)
+++ lldb/trunk/source/Core/Value.cpp Wed Dec  5 20:33:54 2012
@@ -201,8 +201,7 @@
         if (GetRegisterInfo())
             byte_size = GetRegisterInfo()->byte_size;
         else if (error_ptr)
-                error_ptr->SetErrorString ("Can't determine byte size with NULL RegisterInfo *.");
-
+            error_ptr->SetErrorString ("Can't determine byte size with NULL RegisterInfo *.");
         break;
 
     case eContextTypeLLDBType:             // Type *

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=169465&r1=169464&r2=169465&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Wed Dec  5 20:33:54 2012
@@ -675,7 +675,7 @@
                                                                   child_bitfield_bit_offset,
                                                                   child_is_base_class,
                                                                   child_is_deref_of_parent);
-    if (child_clang_type && child_byte_size)
+    if (child_clang_type)
     {
         if (synthetic_index)
             child_byte_offset += child_byte_size * synthetic_index;
@@ -1798,7 +1798,7 @@
 bool
 ValueObject::IsArrayType ()
 {
-    return ClangASTContext::IsArrayType (GetClangType());
+    return ClangASTContext::IsArrayType (GetClangType(), NULL, NULL, NULL);
 }
 
 bool

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=169465&r1=169464&r2=169465&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Wed Dec  5 20:33:54 2012
@@ -4218,6 +4218,7 @@
                     uint64_t num_elements = 0;
                     uint64_t lower_bound = 0;
                     uint64_t upper_bound = 0;
+                    bool upper_bound_valid = false;
                     uint32_t i;
                     for (i=0; i<num_child_attributes; ++i)
                     {
@@ -4247,6 +4248,7 @@
                                 break;
 
                             case DW_AT_upper_bound:
+                                upper_bound_valid = true;
                                 upper_bound = form_value.Unsigned();
                                 break;
 
@@ -4269,7 +4271,7 @@
 
                     if (num_elements == 0)
                     {
-                        if (upper_bound >= lower_bound)
+                        if (upper_bound_valid && upper_bound >= lower_bound)
                             num_elements = upper_bound - lower_bound + 1;
                     }
 
@@ -6534,10 +6536,9 @@
                             {
                                 num_elements = *pos;
                                 clang_type = ast.CreateArrayType (array_element_type, 
-                                                                  num_elements, 
-                                                                  num_elements * array_element_bit_stride);
+                                                                  num_elements);
                                 array_element_type = clang_type;
-                                array_element_bit_stride = array_element_bit_stride * num_elements;
+                                array_element_bit_stride = num_elements ? array_element_bit_stride * num_elements : array_element_bit_stride;
                             }
                             ConstString empty_name;
                             type_sp.reset( new Type (MakeUserID(die->GetOffset()), 

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=169465&r1=169464&r2=169465&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Wed Dec  5 20:33:54 2012
@@ -2046,14 +2046,14 @@
     typedef llvm::SmallVector <IndirectFieldDecl *, 1> IndirectFieldVector;
     
     IndirectFieldVector indirect_fields;
-    
-    for (RecordDecl::field_iterator fi = record_decl->field_begin(), fe = record_decl->field_end();
-         fi != fe;
-         ++fi)
+    RecordDecl::field_iterator field_pos;
+    RecordDecl::field_iterator field_end_pos = record_decl->field_end();
+    RecordDecl::field_iterator last_field_pos = field_end_pos;
+    for (field_pos = record_decl->field_begin(); field_pos != field_end_pos; last_field_pos = field_pos++)
     {
-        if (fi->isAnonymousStructOrUnion())
+        if (field_pos->isAnonymousStructOrUnion())
         {
-            QualType field_qual_type = fi->getType();
+            QualType field_qual_type = field_pos->getType();
             
             const RecordType *field_record_type = field_qual_type->getAs<RecordType>();
             
@@ -2072,7 +2072,7 @@
                 if (FieldDecl *nested_field_decl = dyn_cast<FieldDecl>(*di))
                 {
                     NamedDecl **chain = new (*ast) NamedDecl*[2];
-                    chain[0] = *fi;
+                    chain[0] = *field_pos;
                     chain[1] = nested_field_decl;
                     IndirectFieldDecl *indirect_field = IndirectFieldDecl::Create(*ast,
                                                                                   record_decl,
@@ -2082,7 +2082,7 @@
                                                                                   chain,
                                                                                   2);
                     
-                    indirect_field->setAccess(UnifyAccessSpecifiers(fi->getAccess(),
+                    indirect_field->setAccess(UnifyAccessSpecifiers(field_pos->getAccess(),
                                                                     nested_field_decl->getAccess()));
                     
                     indirect_fields.push_back(indirect_field);
@@ -2091,7 +2091,7 @@
                 {
                     int nested_chain_size = nested_indirect_field_decl->getChainingSize();
                     NamedDecl **chain = new (*ast) NamedDecl*[nested_chain_size + 1];
-                    chain[0] = *fi;
+                    chain[0] = *field_pos;
                     
                     int chain_index = 1;
                     for (IndirectFieldDecl::chain_iterator nci = nested_indirect_field_decl->chain_begin(),
@@ -2111,7 +2111,7 @@
                                                                                   chain,
                                                                                   nested_chain_size + 1);
                                         
-                    indirect_field->setAccess(UnifyAccessSpecifiers(fi->getAccess(),
+                    indirect_field->setAccess(UnifyAccessSpecifiers(field_pos->getAccess(),
                                                                     nested_indirect_field_decl->getAccess()));
                     
                     indirect_fields.push_back(indirect_field);
@@ -2120,6 +2120,14 @@
         }
     }
     
+    // Check the last field to see if it has an incomplete array type as its
+    // last member and if it does, the tell the record decl about it
+    if (last_field_pos != field_end_pos)
+    {
+        if (last_field_pos->getType()->isIncompleteArrayType())
+            record_decl->hasFlexibleArrayMember();
+    }
+    
     for (IndirectFieldVector::iterator ifi = indirect_fields.begin(), ife = indirect_fields.end();
          ifi < ife;
          ++ifi)
@@ -3864,17 +3872,19 @@
     if (parent_clang_type == NULL)
         return NULL;
 
-    if (idx < ClangASTContext::GetNumChildren (ast, parent_clang_type, omit_empty_base_classes))
+    QualType parent_qual_type(QualType::getFromOpaquePtr(parent_clang_type));
+    const clang::Type::TypeClass parent_type_class = parent_qual_type->getTypeClass();
+    child_bitfield_bit_size = 0;
+    child_bitfield_bit_offset = 0;
+    child_is_base_class = false;
+
+    const bool idx_is_valid = idx < ClangASTContext::GetNumChildren (ast, parent_clang_type, omit_empty_base_classes);
+    uint32_t bit_offset;
+    switch (parent_type_class)
     {
-        uint32_t bit_offset;
-        child_bitfield_bit_size = 0;
-        child_bitfield_bit_offset = 0;
-        child_is_base_class = false;
-        QualType parent_qual_type(QualType::getFromOpaquePtr(parent_clang_type));
-        const clang::Type::TypeClass parent_type_class = parent_qual_type->getTypeClass();
-        switch (parent_type_class)
+    case clang::Type::Builtin:
+        if (idx_is_valid)
         {
-        case clang::Type::Builtin:
             switch (cast<clang::BuiltinType>(parent_qual_type)->getKind())
             {
             case clang::BuiltinType::ObjCId:
@@ -3886,270 +3896,272 @@
             default:
                 break;
             }
-            break;
+        }
+        break;
 
-        case clang::Type::Record:
-            if (GetCompleteQualType (ast, parent_qual_type))
-            {
-                const RecordType *record_type = cast<RecordType>(parent_qual_type.getTypePtr());
-                const RecordDecl *record_decl = record_type->getDecl();
-                assert(record_decl);
-                const ASTRecordLayout &record_layout = ast->getASTRecordLayout(record_decl);
-                uint32_t child_idx = 0;
+    case clang::Type::Record:
+        if (idx_is_valid && GetCompleteQualType (ast, parent_qual_type))
+        {
+            const RecordType *record_type = cast<RecordType>(parent_qual_type.getTypePtr());
+            const RecordDecl *record_decl = record_type->getDecl();
+            assert(record_decl);
+            const ASTRecordLayout &record_layout = ast->getASTRecordLayout(record_decl);
+            uint32_t child_idx = 0;
 
-                const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
-                if (cxx_record_decl)
+            const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
+            if (cxx_record_decl)
+            {
+                // We might have base classes to print out first
+                CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
+                for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
+                     base_class != base_class_end;
+                     ++base_class)
                 {
-                    // We might have base classes to print out first
-                    CXXRecordDecl::base_class_const_iterator base_class, base_class_end;
-                    for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end();
-                         base_class != base_class_end;
-                         ++base_class)
+                    const CXXRecordDecl *base_class_decl = NULL;
+
+                    // Skip empty base classes
+                    if (omit_empty_base_classes)
                     {
-                        const CXXRecordDecl *base_class_decl = NULL;
+                        base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
+                        if (RecordHasFields(base_class_decl) == false)
+                            continue;
+                    }
 
-                        // Skip empty base classes
-                        if (omit_empty_base_classes)
-                        {
+                    if (idx == child_idx)
+                    {
+                        if (base_class_decl == NULL)
                             base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
-                            if (RecordHasFields(base_class_decl) == false)
-                                continue;
-                        }
-
-                        if (idx == child_idx)
-                        {
-                            if (base_class_decl == NULL)
-                                base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl());
 
 
-                            if (base_class->isVirtual())
-                                bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
-                            else
-                                bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8;
+                        if (base_class->isVirtual())
+                            bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8;
+                        else
+                            bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8;
 
-                            // Base classes should be a multiple of 8 bits in size
-                            child_byte_offset = bit_offset/8;
-                            
-                            child_name = ClangASTType::GetTypeNameForQualType(ast, base_class->getType());
+                        // Base classes should be a multiple of 8 bits in size
+                        child_byte_offset = bit_offset/8;
+                        
+                        child_name = ClangASTType::GetTypeNameForQualType(ast, base_class->getType());
 
-                            uint64_t clang_type_info_bit_size = ast->getTypeSize(base_class->getType());
+                        uint64_t clang_type_info_bit_size = ast->getTypeSize(base_class->getType());
 
-                            // Base classes bit sizes should be a multiple of 8 bits in size
-                            assert (clang_type_info_bit_size % 8 == 0);
-                            child_byte_size = clang_type_info_bit_size / 8;
-                            child_is_base_class = true;
-                            return base_class->getType().getAsOpaquePtr();
-                        }
-                        // We don't increment the child index in the for loop since we might
-                        // be skipping empty base classes
-                        ++child_idx;
+                        // Base classes bit sizes should be a multiple of 8 bits in size
+                        assert (clang_type_info_bit_size % 8 == 0);
+                        child_byte_size = clang_type_info_bit_size / 8;
+                        child_is_base_class = true;
+                        return base_class->getType().getAsOpaquePtr();
                     }
+                    // We don't increment the child index in the for loop since we might
+                    // be skipping empty base classes
+                    ++child_idx;
                 }
-                // Make sure index is in range...
-                uint32_t field_idx = 0;
-                RecordDecl::field_iterator field, field_end;
-                for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx)
+            }
+            // Make sure index is in range...
+            uint32_t field_idx = 0;
+            RecordDecl::field_iterator field, field_end;
+            for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx)
+            {
+                if (idx == child_idx)
                 {
-                    if (idx == child_idx)
-                    {
-                        // Print the member type if requested
-                        // Print the member name and equal sign
-                        child_name.assign(field->getNameAsString().c_str());
+                    // Print the member type if requested
+                    // Print the member name and equal sign
+                    child_name.assign(field->getNameAsString().c_str());
 
-                        // Figure out the type byte size (field_type_info.first) and
-                        // alignment (field_type_info.second) from the AST context.
-                        std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(field->getType());
-                        assert(field_idx < record_layout.getFieldCount());
+                    // Figure out the type byte size (field_type_info.first) and
+                    // alignment (field_type_info.second) from the AST context.
+                    std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(field->getType());
+                    assert(field_idx < record_layout.getFieldCount());
 
-                        child_byte_size = field_type_info.first / 8;
+                    child_byte_size = field_type_info.first / 8;
 
-                        // Figure out the field offset within the current struct/union/class type
-                        bit_offset = record_layout.getFieldOffset (field_idx);
-                        child_byte_offset = bit_offset / 8;
-                        if (ClangASTContext::FieldIsBitfield (ast, *field, child_bitfield_bit_size))
-                            child_bitfield_bit_offset = bit_offset % 8;
+                    // Figure out the field offset within the current struct/union/class type
+                    bit_offset = record_layout.getFieldOffset (field_idx);
+                    child_byte_offset = bit_offset / 8;
+                    if (ClangASTContext::FieldIsBitfield (ast, *field, child_bitfield_bit_size))
+                        child_bitfield_bit_offset = bit_offset % 8;
 
-                        return field->getType().getAsOpaquePtr();
-                    }
+                    return field->getType().getAsOpaquePtr();
                 }
             }
-            break;
+        }
+        break;
 
-        case clang::Type::ObjCObject:
-        case clang::Type::ObjCInterface:
-            if (GetCompleteQualType (ast, parent_qual_type))
+    case clang::Type::ObjCObject:
+    case clang::Type::ObjCInterface:
+        if (idx_is_valid && GetCompleteQualType (ast, parent_qual_type))
+        {
+            const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(parent_qual_type.getTypePtr());
+            assert (objc_class_type);
+            if (objc_class_type)
             {
-                const ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(parent_qual_type.getTypePtr());
-                assert (objc_class_type);
-                if (objc_class_type)
+                uint32_t child_idx = 0;
+                ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+            
+                if (class_interface_decl)
                 {
-                    uint32_t child_idx = 0;
-                    ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
-                
-                    if (class_interface_decl)
+            
+                    const ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl);
+                    ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+                    if (superclass_interface_decl)
                     {
-                
-                        const ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl);
-                        ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
-                        if (superclass_interface_decl)
+                        if (omit_empty_base_classes)
                         {
-                            if (omit_empty_base_classes)
+                            if (ClangASTContext::GetNumChildren(ast, ast->getObjCInterfaceType(superclass_interface_decl).getAsOpaquePtr(), omit_empty_base_classes) > 0)
                             {
-                                if (ClangASTContext::GetNumChildren(ast, ast->getObjCInterfaceType(superclass_interface_decl).getAsOpaquePtr(), omit_empty_base_classes) > 0)
+                                if (idx == 0)
                                 {
-                                    if (idx == 0)
-                                    {
-                                        QualType ivar_qual_type(ast->getObjCInterfaceType(superclass_interface_decl));
-                                        
-
-                                        child_name.assign(superclass_interface_decl->getNameAsString().c_str());
+                                    QualType ivar_qual_type(ast->getObjCInterfaceType(superclass_interface_decl));
+                                    
 
-                                        std::pair<uint64_t, unsigned> ivar_type_info = ast->getTypeInfo(ivar_qual_type.getTypePtr());
+                                    child_name.assign(superclass_interface_decl->getNameAsString().c_str());
 
-                                        child_byte_size = ivar_type_info.first / 8;
-                                        child_byte_offset = 0;
-                                        child_is_base_class = true;
+                                    std::pair<uint64_t, unsigned> ivar_type_info = ast->getTypeInfo(ivar_qual_type.getTypePtr());
 
-                                        return ivar_qual_type.getAsOpaquePtr();
-                                    }
+                                    child_byte_size = ivar_type_info.first / 8;
+                                    child_byte_offset = 0;
+                                    child_is_base_class = true;
 
-                                    ++child_idx;
+                                    return ivar_qual_type.getAsOpaquePtr();
                                 }
-                            }
-                            else
+
                                 ++child_idx;
+                            }
                         }
-    
-                        const uint32_t superclass_idx = child_idx;
+                        else
+                            ++child_idx;
+                    }
 
-                        if (idx < (child_idx + class_interface_decl->ivar_size()))
+                    const uint32_t superclass_idx = child_idx;
+
+                    if (idx < (child_idx + class_interface_decl->ivar_size()))
+                    {
+                        ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
+                        
+                        for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos)
                         {
-                            ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
-                            
-                            for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos)
+                            if (child_idx == idx)
                             {
-                                if (child_idx == idx)
+                                ObjCIvarDecl* ivar_decl = *ivar_pos;
+                                
+                                QualType ivar_qual_type(ivar_decl->getType());
+
+                                child_name.assign(ivar_decl->getNameAsString().c_str());
+
+                                std::pair<uint64_t, unsigned> ivar_type_info = ast->getTypeInfo(ivar_qual_type.getTypePtr());
+
+                                child_byte_size = ivar_type_info.first / 8;
+
+                                // Figure out the field offset within the current struct/union/class type
+                                // For ObjC objects, we can't trust the bit offset we get from the Clang AST, since
+                                // that doesn't account for the space taken up by unbacked properties, or from 
+                                // the changing size of base classes that are newer than this class.
+                                // So if we have a process around that we can ask about this object, do so.
+                                child_byte_offset = LLDB_INVALID_IVAR_OFFSET;
+                                Process *process = NULL;
+                                if (exe_ctx)
+                                    process = exe_ctx->GetProcessPtr();
+                                if (process)
                                 {
-                                    ObjCIvarDecl* ivar_decl = *ivar_pos;
-                                    
-                                    QualType ivar_qual_type(ivar_decl->getType());
-
-                                    child_name.assign(ivar_decl->getNameAsString().c_str());
-
-                                    std::pair<uint64_t, unsigned> ivar_type_info = ast->getTypeInfo(ivar_qual_type.getTypePtr());
-
-                                    child_byte_size = ivar_type_info.first / 8;
-
-                                    // Figure out the field offset within the current struct/union/class type
-                                    // For ObjC objects, we can't trust the bit offset we get from the Clang AST, since
-                                    // that doesn't account for the space taken up by unbacked properties, or from 
-                                    // the changing size of base classes that are newer than this class.
-                                    // So if we have a process around that we can ask about this object, do so.
-                                    child_byte_offset = LLDB_INVALID_IVAR_OFFSET;
-                                    Process *process = NULL;
-                                    if (exe_ctx)
-                                        process = exe_ctx->GetProcessPtr();
-                                    if (process)
+                                    ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
+                                    if (objc_runtime != NULL)
                                     {
-                                        ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
-                                        if (objc_runtime != NULL)
-                                        {
-                                            ClangASTType parent_ast_type (ast, parent_qual_type.getAsOpaquePtr());
-                                            child_byte_offset = objc_runtime->GetByteOffsetForIvar (parent_ast_type, ivar_decl->getNameAsString().c_str());
-                                        }
+                                        ClangASTType parent_ast_type (ast, parent_qual_type.getAsOpaquePtr());
+                                        child_byte_offset = objc_runtime->GetByteOffsetForIvar (parent_ast_type, ivar_decl->getNameAsString().c_str());
                                     }
-                                    
-                                    // Setting this to UINT32_MAX to make sure we don't compute it twice...
-                                    bit_offset = UINT32_MAX;
-                                    
-                                    if (child_byte_offset == LLDB_INVALID_IVAR_OFFSET)
-                                    {
+                                }
+                                
+                                // Setting this to UINT32_MAX to make sure we don't compute it twice...
+                                bit_offset = UINT32_MAX;
+                                
+                                if (child_byte_offset == LLDB_INVALID_IVAR_OFFSET)
+                                {
+                                    bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx);
+                                    child_byte_offset = bit_offset / 8;
+                                }
+                                
+                                // Note, the ObjC Ivar Byte offset is just that, it doesn't account for the bit offset
+                                // of a bitfield within its containing object.  So regardless of where we get the byte
+                                // offset from, we still need to get the bit offset for bitfields from the layout.
+                                
+                                if (ClangASTContext::FieldIsBitfield (ast, ivar_decl, child_bitfield_bit_size))
+                                {
+                                    if (bit_offset == UINT32_MAX)
                                         bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx);
-                                        child_byte_offset = bit_offset / 8;
-                                    }
-                                    
-                                    // Note, the ObjC Ivar Byte offset is just that, it doesn't account for the bit offset
-                                    // of a bitfield within its containing object.  So regardless of where we get the byte
-                                    // offset from, we still need to get the bit offset for bitfields from the layout.
-                                    
-                                    if (ClangASTContext::FieldIsBitfield (ast, ivar_decl, child_bitfield_bit_size))
-                                    {
-                                        if (bit_offset == UINT32_MAX)
-                                            bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx);
-                                            
-                                        child_bitfield_bit_offset = bit_offset % 8;
-                                    }
-                                    return ivar_qual_type.getAsOpaquePtr();
+                                        
+                                    child_bitfield_bit_offset = bit_offset % 8;
                                 }
-                                ++child_idx;
+                                return ivar_qual_type.getAsOpaquePtr();
                             }
+                            ++child_idx;
                         }
                     }
                 }
             }
-            break;
-            
-        case clang::Type::ObjCObjectPointer:
-            {
-                const ObjCObjectPointerType *pointer_type = cast<ObjCObjectPointerType>(parent_qual_type.getTypePtr());
-                QualType pointee_type = pointer_type->getPointeeType();
+        }
+        break;
+        
+    case clang::Type::ObjCObjectPointer:
+        if (idx_is_valid)
+        {
+            const ObjCObjectPointerType *pointer_type = cast<ObjCObjectPointerType>(parent_qual_type.getTypePtr());
+            QualType pointee_type = pointer_type->getPointeeType();
 
-                if (transparent_pointers && ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+            if (transparent_pointers && ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+            {
+                child_is_deref_of_parent = false;
+                bool tmp_child_is_deref_of_parent = false;
+                return GetChildClangTypeAtIndex (exe_ctx,
+                                                 ast,
+                                                 parent_name,
+                                                 pointer_type->getPointeeType().getAsOpaquePtr(),
+                                                 idx,
+                                                 transparent_pointers,
+                                                 omit_empty_base_classes,
+                                                 ignore_array_bounds,
+                                                 child_name,
+                                                 child_byte_size,
+                                                 child_byte_offset,
+                                                 child_bitfield_bit_size,
+                                                 child_bitfield_bit_offset,
+                                                 child_is_base_class,
+                                                 tmp_child_is_deref_of_parent);
+            }
+            else
+            {
+                child_is_deref_of_parent = true;
+                if (parent_name)
                 {
-                    child_is_deref_of_parent = false;
-                    bool tmp_child_is_deref_of_parent = false;
-                    return GetChildClangTypeAtIndex (exe_ctx,
-                                                     ast,
-                                                     parent_name,
-                                                     pointer_type->getPointeeType().getAsOpaquePtr(),
-                                                     idx,
-                                                     transparent_pointers,
-                                                     omit_empty_base_classes,
-                                                     ignore_array_bounds,
-                                                     child_name,
-                                                     child_byte_size,
-                                                     child_byte_offset,
-                                                     child_bitfield_bit_size,
-                                                     child_bitfield_bit_offset,
-                                                     child_is_base_class,
-                                                     tmp_child_is_deref_of_parent);
+                    child_name.assign(1, '*');
+                    child_name += parent_name;
                 }
-                else
-                {
-                    child_is_deref_of_parent = true;
-                    if (parent_name)
-                    {
-                        child_name.assign(1, '*');
-                        child_name += parent_name;
-                    }
 
-                    // We have a pointer to an simple type
-                    if (idx == 0 && GetCompleteQualType(ast, pointee_type))
-                    {
-                        std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type);
-                        assert(clang_type_info.first % 8 == 0);
-                        child_byte_size = clang_type_info.first / 8;
-                        child_byte_offset = 0;
-                        return pointee_type.getAsOpaquePtr();
-                    }
+                // We have a pointer to an simple type
+                if (idx == 0 && GetCompleteQualType(ast, pointee_type))
+                {
+                    std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type);
+                    assert(clang_type_info.first % 8 == 0);
+                    child_byte_size = clang_type_info.first / 8;
+                    child_byte_offset = 0;
+                    return pointee_type.getAsOpaquePtr();
                 }
             }
-            break;
+        }
+        break;
 
         case clang::Type::ConstantArray:
+        case clang::Type::IncompleteArray:
+            if (ignore_array_bounds || idx_is_valid)
             {
-                const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr());
-                const uint64_t element_count = array->getSize().getLimitedValue();
-
-                if (ignore_array_bounds || idx < element_count)
+                const ArrayType *array = cast<ArrayType>(parent_qual_type.getTypePtr());
+                if (array)
                 {
                     if (GetCompleteQualType (ast, array->getElementType()))
                     {
                         std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(array->getElementType());
-
+                        
                         char element_name[64];
                         ::snprintf (element_name, sizeof (element_name), "[%u]", idx);
-
+                        
                         child_name.assign(element_name);
                         assert(field_type_info.first % 8 == 0);
                         child_byte_size = field_type_info.first / 8;
@@ -4159,144 +4171,146 @@
                 }
             }
             break;
+            
 
-        case clang::Type::Pointer:
+    case clang::Type::Pointer:
+        if (idx_is_valid)
+        {
+            const PointerType *pointer_type = cast<PointerType>(parent_qual_type.getTypePtr());
+            QualType pointee_type = pointer_type->getPointeeType();
+            
+            // Don't dereference "void *" pointers
+            if (pointee_type->isVoidType())
+                return NULL;
+
+            if (transparent_pointers && ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
+            {
+                child_is_deref_of_parent = false;
+                bool tmp_child_is_deref_of_parent = false;
+                return GetChildClangTypeAtIndex (exe_ctx,
+                                                 ast,
+                                                 parent_name,
+                                                 pointer_type->getPointeeType().getAsOpaquePtr(),
+                                                 idx,
+                                                 transparent_pointers,
+                                                 omit_empty_base_classes,
+                                                 ignore_array_bounds,
+                                                 child_name,
+                                                 child_byte_size,
+                                                 child_byte_offset,
+                                                 child_bitfield_bit_size,
+                                                 child_bitfield_bit_offset,
+                                                 child_is_base_class,
+                                                 tmp_child_is_deref_of_parent);
+            }
+            else
             {
-                const PointerType *pointer_type = cast<PointerType>(parent_qual_type.getTypePtr());
-                QualType pointee_type = pointer_type->getPointeeType();
-                
-                // Don't dereference "void *" pointers
-                if (pointee_type->isVoidType())
-                    return NULL;
-
-                if (transparent_pointers && ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr()))
-                {
-                    child_is_deref_of_parent = false;
-                    bool tmp_child_is_deref_of_parent = false;
-                    return GetChildClangTypeAtIndex (exe_ctx,
-                                                     ast,
-                                                     parent_name,
-                                                     pointer_type->getPointeeType().getAsOpaquePtr(),
-                                                     idx,
-                                                     transparent_pointers,
-                                                     omit_empty_base_classes,
-                                                     ignore_array_bounds,
-                                                     child_name,
-                                                     child_byte_size,
-                                                     child_byte_offset,
-                                                     child_bitfield_bit_size,
-                                                     child_bitfield_bit_offset,
-                                                     child_is_base_class,
-                                                     tmp_child_is_deref_of_parent);
-                }
-                else
-                {
-                    child_is_deref_of_parent = true;
+                child_is_deref_of_parent = true;
 
-                    if (parent_name)
-                    {
-                        child_name.assign(1, '*');
-                        child_name += parent_name;
-                    }
+                if (parent_name)
+                {
+                    child_name.assign(1, '*');
+                    child_name += parent_name;
+                }
 
-                    // We have a pointer to an simple type
-                    if (idx == 0)
-                    {
-                        std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type);
-                        assert(clang_type_info.first % 8 == 0);
-                        child_byte_size = clang_type_info.first / 8;
-                        child_byte_offset = 0;
-                        return pointee_type.getAsOpaquePtr();
-                    }
+                // We have a pointer to an simple type
+                if (idx == 0)
+                {
+                    std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type);
+                    assert(clang_type_info.first % 8 == 0);
+                    child_byte_size = clang_type_info.first / 8;
+                    child_byte_offset = 0;
+                    return pointee_type.getAsOpaquePtr();
                 }
             }
-            break;
+        }
+        break;
 
-        case clang::Type::LValueReference:
-        case clang::Type::RValueReference:
+    case clang::Type::LValueReference:
+    case clang::Type::RValueReference:
+        if (idx_is_valid)
+        {
+            const ReferenceType *reference_type = cast<ReferenceType>(parent_qual_type.getTypePtr());
+            QualType pointee_type(reference_type->getPointeeType());
+            clang_type_t pointee_clang_type = pointee_type.getAsOpaquePtr();
+            if (transparent_pointers && ClangASTContext::IsAggregateType (pointee_clang_type))
+            {
+                child_is_deref_of_parent = false;
+                bool tmp_child_is_deref_of_parent = false;
+                return GetChildClangTypeAtIndex (exe_ctx,
+                                                 ast,
+                                                 parent_name,
+                                                 pointee_clang_type,
+                                                 idx,
+                                                 transparent_pointers,
+                                                 omit_empty_base_classes,
+                                                 ignore_array_bounds,
+                                                 child_name,
+                                                 child_byte_size,
+                                                 child_byte_offset,
+                                                 child_bitfield_bit_size,
+                                                 child_bitfield_bit_offset,
+                                                 child_is_base_class,
+                                                 tmp_child_is_deref_of_parent);
+            }
+            else
             {
-                const ReferenceType *reference_type = cast<ReferenceType>(parent_qual_type.getTypePtr());
-                QualType pointee_type(reference_type->getPointeeType());
-                clang_type_t pointee_clang_type = pointee_type.getAsOpaquePtr();
-                if (transparent_pointers && ClangASTContext::IsAggregateType (pointee_clang_type))
-                {
-                    child_is_deref_of_parent = false;
-                    bool tmp_child_is_deref_of_parent = false;
-                    return GetChildClangTypeAtIndex (exe_ctx,
-                                                     ast,
-                                                     parent_name,
-                                                     pointee_clang_type,
-                                                     idx,
-                                                     transparent_pointers,
-                                                     omit_empty_base_classes,
-                                                     ignore_array_bounds,
-                                                     child_name,
-                                                     child_byte_size,
-                                                     child_byte_offset,
-                                                     child_bitfield_bit_size,
-                                                     child_bitfield_bit_offset,
-                                                     child_is_base_class,
-                                                     tmp_child_is_deref_of_parent);
-                }
-                else
+                if (parent_name)
                 {
-                    if (parent_name)
-                    {
-                        child_name.assign(1, '&');
-                        child_name += parent_name;
-                    }
+                    child_name.assign(1, '&');
+                    child_name += parent_name;
+                }
 
-                    // We have a pointer to an simple type
-                    if (idx == 0)
-                    {
-                        std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type);
-                        assert(clang_type_info.first % 8 == 0);
-                        child_byte_size = clang_type_info.first / 8;
-                        child_byte_offset = 0;
-                        return pointee_type.getAsOpaquePtr();
-                    }
+                // We have a pointer to an simple type
+                if (idx == 0)
+                {
+                    std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type);
+                    assert(clang_type_info.first % 8 == 0);
+                    child_byte_size = clang_type_info.first / 8;
+                    child_byte_offset = 0;
+                    return pointee_type.getAsOpaquePtr();
                 }
             }
-            break;
+        }
+        break;
 
-        case clang::Type::Typedef:
-            return GetChildClangTypeAtIndex (exe_ctx,
-                                             ast,
-                                             parent_name,
-                                             cast<TypedefType>(parent_qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(),
-                                             idx,
-                                             transparent_pointers,
-                                             omit_empty_base_classes,
-                                             ignore_array_bounds,
-                                             child_name,
-                                             child_byte_size,
-                                             child_byte_offset,
-                                             child_bitfield_bit_size,
-                                             child_bitfield_bit_offset,
-                                             child_is_base_class,
-                                             child_is_deref_of_parent);
-            break;
-    
-        case clang::Type::Elaborated:
-            return GetChildClangTypeAtIndex (exe_ctx,
-                                             ast,
-                                             parent_name,
-                                             cast<ElaboratedType>(parent_qual_type)->getNamedType().getAsOpaquePtr(),
-                                             idx,
-                                             transparent_pointers,
-                                             omit_empty_base_classes,
-                                             ignore_array_bounds,
-                                             child_name,
-                                             child_byte_size,
-                                             child_byte_offset,
-                                             child_bitfield_bit_size,
-                                             child_bitfield_bit_offset,
-                                             child_is_base_class,
-                                             child_is_deref_of_parent); 
+    case clang::Type::Typedef:
+        return GetChildClangTypeAtIndex (exe_ctx,
+                                         ast,
+                                         parent_name,
+                                         cast<TypedefType>(parent_qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(),
+                                         idx,
+                                         transparent_pointers,
+                                         omit_empty_base_classes,
+                                         ignore_array_bounds,
+                                         child_name,
+                                         child_byte_size,
+                                         child_byte_offset,
+                                         child_bitfield_bit_size,
+                                         child_bitfield_bit_offset,
+                                         child_is_base_class,
+                                         child_is_deref_of_parent);
+        break;
 
-        default:
-            break;
-        }
+    case clang::Type::Elaborated:
+        return GetChildClangTypeAtIndex (exe_ctx,
+                                         ast,
+                                         parent_name,
+                                         cast<ElaboratedType>(parent_qual_type)->getNamedType().getAsOpaquePtr(),
+                                         idx,
+                                         transparent_pointers,
+                                         omit_empty_base_classes,
+                                         ignore_array_bounds,
+                                         child_name,
+                                         child_byte_size,
+                                         child_byte_offset,
+                                         child_bitfield_bit_size,
+                                         child_bitfield_bit_offset,
+                                         child_is_base_class,
+                                         child_is_deref_of_parent); 
+
+    default:
+        break;
     }
     return NULL;
 }
@@ -5250,17 +5264,27 @@
 #pragma mark Array Types
 
 clang_type_t
-ClangASTContext::CreateArrayType (clang_type_t element_type, size_t element_count, uint32_t bit_stride)
+ClangASTContext::CreateArrayType (clang_type_t element_type, size_t element_count)
 {
     if (element_type)
     {
         ASTContext *ast = getASTContext();
         assert (ast != NULL);
         llvm::APInt ap_element_count (64, element_count);
-        return ast->getConstantArrayType(QualType::getFromOpaquePtr(element_type),
-                                                 ap_element_count,
-                                                 ArrayType::Normal,
-                                                 0).getAsOpaquePtr(); // ElemQuals
+        if (element_count == 0)
+        {
+            return ast->getIncompleteArrayType(QualType::getFromOpaquePtr(element_type),
+                                               ArrayType::Normal,
+                                               0).getAsOpaquePtr();
+
+        }
+        else
+        {
+            return ast->getConstantArrayType(QualType::getFromOpaquePtr(element_type),
+                                                     ap_element_count,
+                                                     ArrayType::Normal,
+                                                     0).getAsOpaquePtr(); // ElemQuals
+        }
     }
     return NULL;
 }
@@ -5931,7 +5955,7 @@
 bool
 ClangASTContext::IsArrayOfScalarType (lldb::clang_type_t clang_type)
 {
-    clang_type = GetAsArrayType(clang_type);
+    clang_type = GetAsArrayType(clang_type, NULL, NULL, NULL);
     
     if (clang_type == 0)
         return false;
@@ -6151,8 +6175,10 @@
 }
 
 clang_type_t
-ClangASTContext::GetAsArrayType (clang_type_t clang_type, clang_type_t*member_type, uint64_t *size)
+ClangASTContext::GetAsArrayType (clang_type_t clang_type, clang_type_t*member_type, uint64_t *size, bool *is_incomplete)
 {
+    if (is_incomplete)
+        *is_incomplete = false;
     if (!clang_type)
         return 0;
     
@@ -6176,6 +6202,8 @@
             *member_type = cast<IncompleteArrayType>(qual_type)->getElementType().getAsOpaquePtr();
         if (size)
             *size = 0;
+        if (is_incomplete)
+            *is_incomplete = true;
         return clang_type;
 
     case clang::Type::VariableArray:
@@ -6195,12 +6223,14 @@
     case clang::Type::Typedef:
         return ClangASTContext::GetAsArrayType (cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(),
                                                 member_type, 
-                                                size);
+                                                size,
+                                                is_incomplete);
     
     case clang::Type::Elaborated:
         return ClangASTContext::GetAsArrayType (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(),
                                                 member_type,
-                                                size);
+                                                size,
+                                                is_incomplete);
     }
     return 0;
 }

Modified: lldb/trunk/source/Symbol/ClangASTType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTType.cpp?rev=169465&r1=169464&r2=169465&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTType.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTType.cpp Wed Dec  5 20:33:54 2012
@@ -1178,7 +1178,13 @@
     if (ClangASTContext::GetCompleteType (ast_context, clang_type))
     {
         clang::QualType qual_type(clang::QualType::getFromOpaquePtr(clang_type));
-        return ast_context->getTypeSize (qual_type);
+        const uint32_t bit_size = ast_context->getTypeSize (qual_type);
+        if (bit_size == 0)
+        {
+            if (qual_type->isIncompleteArrayType())
+                return ast_context->getTypeSize (qual_type->getArrayElementTypeNoTypeQual()->getCanonicalTypeUnqualified());
+        }
+        return bit_size;
     }
     return 0;
 }

Modified: lldb/trunk/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=169465&r1=169464&r2=169465&view=diff
==============================================================================
--- lldb/trunk/source/Target/StackFrame.cpp (original)
+++ lldb/trunk/source/Target/StackFrame.cpp Wed Dec  5 20:33:54 2012
@@ -792,6 +792,7 @@
                                     deref = false;
                                 }
                                 
+                                bool is_incomplete_array = false;
                                 if (valobj_sp->IsPointerType ())
                                 {
                                     bool is_objc_pointer = true;
@@ -855,11 +856,14 @@
                                         }
                                     }
                                 }
-                                else if (ClangASTContext::IsArrayType (valobj_sp->GetClangType(), NULL, NULL))
+                                else if (ClangASTContext::IsArrayType (valobj_sp->GetClangType(), NULL, NULL, &is_incomplete_array))
                                 {
                                     // Pass false to dynamic_value here so we can tell the difference between
                                     // no dynamic value and no member of this type...
                                     child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
+                                    if (!child_valobj_sp && (is_incomplete_array || no_synth_child == false))
+                                        child_valobj_sp = valobj_sp->GetSyntheticArrayMember (child_index, true);
+
                                     if (!child_valobj_sp)
                                     {
                                         valobj_sp->GetExpressionPath (var_expr_path_strm, false);

Modified: lldb/trunk/test/lang/c/struct_types/TestStructTypes.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/struct_types/TestStructTypes.py?rev=169465&r1=169464&r2=169465&view=diff
==============================================================================
--- lldb/trunk/test/lang/c/struct_types/TestStructTypes.py (original)
+++ lldb/trunk/test/lang/c/struct_types/TestStructTypes.py Wed Dec  5 20:33:54 2012
@@ -14,6 +14,8 @@
 
     mydir = os.path.join("lang", "c", "struct_types")
 
+    # rdar://problem/12566646
+    @unittest2.expectedFailure
     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     @dsym_test
     def test_with_dsym(self):
@@ -31,19 +33,31 @@
         # Call super's setUp().
         TestBase.setUp(self)
         # Find the line number to break for main.c.
-        self.line = line_number('main.c', '// Set break point at this line.')
-        self.first_executable_line = line_number('main.c',
+        self.source = 'main.c'
+        self.line = line_number(self.source, '// Set break point at this line.')
+        self.first_executable_line = line_number(self.source,
                                                  '// This is the first executable statement.')
+        self.return_line = line_number(self.source, '// This is the return statement.')
 
     def struct_types(self):
-        """Test that break on a struct declaration has no effect."""
+        """Test that break on a struct declaration has no effect and test structure access for zero sized arrays."""
         exe = os.path.join(os.getcwd(), "a.out")
-        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # Create a target by the debugger.
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
 
         # Break on the struct declration statement in main.c.
         lldbutil.run_break_set_by_file_and_line (self, "main.c", self.line, num_expected_locations=1, loc_exact=False)
+        lldbutil.run_break_set_by_file_and_line (self, "main.c", self.return_line, num_expected_locations=1, loc_exact=True)
+
+        # Now launch the process, and do not stop at entry point.
+        process = target.LaunchSimple(None, None, os.getcwd())
 
-        self.runCmd("run", RUN_SUCCEEDED)
+        if not process:
+            self.fail("SBTarget.Launch() failed")
+
+        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
 
         # We should be stopped on the first executable statement within the
         # function where the original breakpoint was attempted.
@@ -55,10 +69,26 @@
         self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
             substrs = [' resolved, hit count = 1'])
 
+        process.Continue()
+        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
+
+        # Test zero length array access and make sure it succeeds with "frame variable"
+        self.expect("frame variable pt.padding[0]",
+            DATA_TYPES_DISPLAYED_CORRECTLY,
+            substrs = ["pt.padding[0] = '"])
+        self.expect("frame variable pt.padding[1]",
+            DATA_TYPES_DISPLAYED_CORRECTLY,
+            substrs = ["pt.padding[1] = '"])
+        # Test zero length array access and make sure it succeeds with "expression"
+        self.expect("expression -- pt.padding[0]",
+            DATA_TYPES_DISPLAYED_CORRECTLY,
+            substrs = ["(char)", " = '"])
+
         # The padding should be an array of size 0
         self.expect("image lookup -t point_tag",
             DATA_TYPES_DISPLAYED_CORRECTLY,
-            substrs = ['padding[0]'])
+            substrs = ['padding[]']) # Once rdar://problem/12566646 is fixed, this should display correctly
+
 
 
 if __name__ == '__main__':

Modified: lldb/trunk/test/lang/c/struct_types/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/struct_types/main.c?rev=169465&r1=169464&r2=169465&view=diff
==============================================================================
--- lldb/trunk/test/lang/c/struct_types/main.c (original)
+++ lldb/trunk/test/lang/c/struct_types/main.c Wed Dec  5 20:33:54 2012
@@ -20,5 +20,5 @@
     };
     struct point_tag pt = { 2, 3, {} }; // This is the first executable statement.
     struct rect_tag rect = {{1, 2, {}}, {3, 4, {}}};
-    return 0;
+    return 0; // This is the return statement.
 }





More information about the lldb-commits mailing list