Created lldb::LanguageType by moving an enumeration from the 
lldb_private::Language class into the enumerations header so it can be freely
used by other interfaces.

Added correct objective C class support to the DWARF symbol parser. Prior to
this fix we were parsing objective C classes as C++ classes and now that the
expression parser is ready to call functions we need to make sure the objective
C classes have correct AST types.



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@109574 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
index 3b1d9c8..52235da 100644
--- a/source/Symbol/ClangASTContext.cpp
+++ b/source/Symbol/ClangASTContext.cpp
@@ -753,7 +753,7 @@
 #pragma mark Structure, Unions, Classes
 
 void *
-ClangASTContext::CreateRecordType (const char *name, int kind, DeclContext *decl_ctx)
+ClangASTContext::CreateRecordType (const char *name, int kind, DeclContext *decl_ctx, lldb::LanguageType language)
 {
     ASTContext *ast_context = getASTContext();
     assert (ast_context != NULL);
@@ -761,6 +761,14 @@
     if (decl_ctx == NULL)
         decl_ctx = ast_context->getTranslationUnitDecl();
 
+
+    if (language == lldb::eLanguageTypeObjC)
+    {
+        bool isForwardDecl = false;
+        bool isInternal = false;
+        return CreateObjCClass (name, decl_ctx, isForwardDecl, isInternal);
+    }
+
     // NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and
     // we will need to update this code. I was told to currently always use
     // the CXXRecordDecl class since we often don't know from debug information
@@ -832,6 +840,20 @@
                 return true;
             }
         }
+        else
+        {
+            ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(clang_type);
+            if (objc_class_type)
+            {
+                bool isSynthesized = false;
+                ClangASTContext::AddObjCClassIVar (record_clang_type,
+                                                   name,
+                                                   field_type,
+                                                   access,
+                                                   bitfield_bit_size,
+                                                   isSynthesized);
+            }
+        }
     }
     return false;
 }
@@ -998,8 +1020,8 @@
                                                          SourceLocation(),
                                                          isForwardDecl,
                                                          isInternal);
-
-    return QualType (decl->getTypeForDecl(), 0).getAsOpaquePtr();
+    
+    return ast_context->getObjCInterfaceType(decl).getAsOpaquePtr();
 }
 
 bool
@@ -1071,27 +1093,61 @@
                     bit_width = new (*ast_context)IntegerLiteral (bitfield_bit_size_apint, ast_context->IntTy, SourceLocation());
                 }
                 
-                //ObjCIvarDecl *field = 
-                ObjCIvarDecl::Create (*ast_context,
-                                      class_interface_decl,
-                                      SourceLocation(),
-                                      &identifier_table->get(name), // Identifier
-                                      QualType::getFromOpaquePtr(ivar_opaque_type), // Field type
-                                      NULL, // TypeSourceInfo *
-                                      ConvertAccessTypeToObjCIvarAccessControl (access),
-                                      bit_width,
-                                      isSynthesized);
-                // TODO: Do I need to do an addDecl? I am thinking I don't since
-                // I passed the "class_interface_decl" into "ObjCIvarDecl::Create"
-                // above. Verify this. Also verify it is ok to pass NULL TypeSourceInfo
-                // above.
-                return true;
+                ObjCIvarDecl *field = ObjCIvarDecl::Create (*ast_context,
+                                                            class_interface_decl,
+                                                            SourceLocation(),
+                                                            &identifier_table->get(name), // Identifier
+                                                            QualType::getFromOpaquePtr(ivar_opaque_type), // Field type
+                                                            NULL, // TypeSourceInfo *
+                                                            ConvertAccessTypeToObjCIvarAccessControl (access),
+                                                            bit_width,
+                                                            isSynthesized);
+                
+                if (field)
+                {
+                    class_interface_decl->addDecl(field);
+                    return true;
+                }
             }
         }
     }
     return false;
 }
 
+
+bool
+ClangASTContext::ObjCTypeHasIVars (void *class_opaque_type, bool check_superclass)
+{
+    QualType class_qual_type(QualType::getFromOpaquePtr(class_opaque_type));
+
+    clang::Type *class_type = class_qual_type.getTypePtr();
+    if (class_type)
+    {
+        ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(class_type);
+
+        if (objc_class_type)
+            return ObjCDeclHasIVars (objc_class_type->getInterface(), check_superclass);
+    }
+    return false;            
+}
+
+bool
+ClangASTContext::ObjCDeclHasIVars (ObjCInterfaceDecl *class_interface_decl, bool check_superclass)
+{
+    while (class_interface_decl)
+    {
+        if (class_interface_decl->ivar_size() > 0)
+            return true;
+        
+        if (check_superclass)
+            class_interface_decl = class_interface_decl->getSuperClass();
+        else
+            break;
+    }
+    return false;            
+}
+    
+
 #pragma mark Aggregate Types
 
 bool
@@ -1113,6 +1169,9 @@
     case clang::Type::ExtVector:
     case clang::Type::Vector:
     case clang::Type::Record:
+    case clang::Type::ObjCObject:
+    case clang::Type::ObjCInterface:
+    case clang::Type::ObjCObjectPointer:
         return true;
 
     case clang::Type::Typedef:
@@ -1133,7 +1192,8 @@
 
     uint32_t num_children = 0;
     QualType qual_type(QualType::getFromOpaquePtr(clang_qual_type));
-    switch (qual_type->getTypeClass())
+    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+    switch (type_class)
     {
     case clang::Type::Record:
         {
@@ -1176,6 +1236,40 @@
         }
         break;
 
+    case clang::Type::ObjCObject:
+    case clang::Type::ObjCInterface:
+        {
+            ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(qual_type.getTypePtr());
+            assert (objc_class_type);
+            if (objc_class_type)
+            {
+                ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+            
+                if (class_interface_decl)
+                {
+            
+                    ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+                    if (superclass_interface_decl)
+                    {
+                        if (omit_empty_base_classes)
+                        {
+                            if (ClangASTContext::ObjCDeclHasIVars (superclass_interface_decl, true))
+                                ++num_children;
+                        }
+                        else
+                            ++num_children;
+                    }
+                    
+                    num_children += class_interface_decl->ivar_size();
+                }
+            }
+        }
+        break;
+        
+    case clang::Type::ObjCObjectPointer:
+        return ClangASTContext::GetNumChildren (cast<ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr(), 
+                                                omit_empty_base_classes);
+
     case clang::Type::ConstantArray:
         num_children = cast<ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue();
         break;
@@ -1184,7 +1278,8 @@
         {
             PointerType *pointer_type = cast<PointerType>(qual_type.getTypePtr());
             QualType pointee_type = pointer_type->getPointeeType();
-            uint32_t num_pointee_children = ClangASTContext::GetNumChildren (pointee_type.getAsOpaquePtr(), omit_empty_base_classes);
+            uint32_t num_pointee_children = ClangASTContext::GetNumChildren (pointee_type.getAsOpaquePtr(), 
+                                                                             omit_empty_base_classes);
             // If this type points to a simple type, then it has 1 child
             if (num_pointee_children == 0)
                 num_children = 1;
@@ -1349,6 +1444,100 @@
             }
             break;
 
+        case clang::Type::ObjCObject:
+        case clang::Type::ObjCInterface:
+            {
+                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)
+                    {
+                
+                        const ASTRecordLayout &interface_layout = ast_context->getASTObjCInterfaceLayout(class_interface_decl);
+                        ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+                        if (superclass_interface_decl)
+                        {
+                            if (omit_empty_base_classes)
+                            {
+                                if (ClangASTContext::GetNumChildren(superclass_interface_decl, omit_empty_base_classes) > 0)
+                                {
+                                    if (idx == 0)
+                                    {
+                                        QualType ivar_qual_type(ast_context->getObjCInterfaceType(superclass_interface_decl));
+                                        
+
+                                        child_name.assign(superclass_interface_decl->getNameAsString().c_str());
+
+                                        std::pair<uint64_t, unsigned> ivar_type_info = ast_context->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
+                                        bit_offset = interface_layout.getFieldOffset (child_idx);
+                                        child_byte_offset = bit_offset / 8;
+
+                                        return ivar_qual_type.getAsOpaquePtr();
+                                    }
+
+                                    ++child_idx;
+                                }
+                            }
+                            else
+                                ++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)
+                            {
+                                if (child_idx == idx)
+                                {
+                                    const 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_context->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
+                                    bit_offset = interface_layout.getFieldOffset (child_idx);
+                                    child_byte_offset = bit_offset / 8;
+
+                                    return ivar_qual_type.getAsOpaquePtr();
+                                }
+                                ++child_idx;
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+            
+        case clang::Type::ObjCObjectPointer:
+            {
+                return GetChildClangTypeAtIndex (ast_context,
+                                                 parent_name,
+                                                 cast<ObjCObjectPointerType>(parent_qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr(),
+                                                 idx,
+                                                 transparent_pointers,
+                                                 omit_empty_base_classes,
+                                                 child_name,
+                                                 child_byte_size,
+                                                 child_byte_offset,
+                                                 child_bitfield_bit_size,
+                                                 child_bitfield_bit_offset);
+            }
+            break;
+
         case clang::Type::ConstantArray:
             {
                 const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr());
@@ -1707,6 +1896,76 @@
             }
             break;
 
+        case clang::Type::ObjCObject:
+        case clang::Type::ObjCInterface:
+            {
+                StringRef name_sref(name);
+                ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(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)
+                    {
+                        ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
+                        ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+                        
+                        for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos)
+                        {
+                            const ObjCIvarDecl* ivar_decl = *ivar_pos;
+                            
+                            if (ivar_decl->getName().equals (name_sref))
+                            {
+                                if ((!omit_empty_base_classes && superclass_interface_decl) || 
+                                    ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true)))
+                                    ++child_idx;
+
+                                child_indexes.push_back (child_idx);
+                                return child_indexes.size();
+                            }
+                        }
+
+                        if (superclass_interface_decl)
+                        {
+                            // The super class index is always zero for ObjC classes,
+                            // so we push it onto the child indexes in case we find
+                            // an ivar in our superclass...
+                            child_indexes.push_back (0);
+                            
+                            if (GetIndexOfChildMemberWithName (ast_context,
+                                                               ast_context->getObjCInterfaceType(superclass_interface_decl).getAsOpaquePtr(),
+                                                               name,
+                                                               omit_empty_base_classes,
+                                                               child_indexes))
+                            {
+                                // We did find an ivar in a superclass so just
+                                // return the results!
+                                return child_indexes.size();
+                            }
+                            
+                            // We didn't find an ivar matching "name" in our 
+                            // superclass, pop the superclass zero index that
+                            // we pushed on above.
+                            child_indexes.pop_back();
+                        }
+                    }
+                }
+            }
+            break;
+            
+        case clang::Type::ObjCObjectPointer:
+            {
+                return GetIndexOfChildMemberWithName (ast_context,
+                                                      cast<ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr(),
+                                                      name,
+                                                      omit_empty_base_classes,
+                                                      child_indexes);
+            }
+            break;
+
+
         case clang::Type::ConstantArray:
             {
 //                const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr());
@@ -1824,7 +2083,10 @@
     if (clang_type && name && name[0])
     {
         QualType qual_type(QualType::getFromOpaquePtr(clang_type));
-        switch (qual_type->getTypeClass())
+        
+        clang::Type::TypeClass qual_type_class = qual_type->getTypeClass();
+
+        switch (qual_type_class)
         {
         case clang::Type::Record:
             {
@@ -1868,6 +2130,55 @@
             }
             break;
 
+        case clang::Type::ObjCObject:
+        case clang::Type::ObjCInterface:
+            {
+                StringRef name_sref(name);
+                ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(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)
+                    {
+                        ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end();
+                        ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass();
+                        
+                        for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos)
+                        {
+                            const ObjCIvarDecl* ivar_decl = *ivar_pos;
+                            
+                            if (ivar_decl->getName().equals (name_sref))
+                            {
+                                if ((!omit_empty_base_classes && superclass_interface_decl) || 
+                                    ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true)))
+                                    ++child_idx;
+
+                                return child_idx;
+                            }
+                        }
+
+                        if (superclass_interface_decl)
+                        {
+                            if (superclass_interface_decl->getName().equals (name_sref))
+                                return 0;
+                        }
+                    }
+                }
+            }
+            break;
+            
+        case clang::Type::ObjCObjectPointer:
+            {
+                return GetIndexOfChildWithName (ast_context,
+                                                cast<ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr(),
+                                                name,
+                                                omit_empty_base_classes);
+            }
+            break;
+
         case clang::Type::ConstantArray:
             {
 //                const ConstantArrayType *array = cast<ConstantArrayType>(parent_qual_type.getTypePtr());
@@ -2003,34 +2314,32 @@
     QualType qual_type(QualType::getFromOpaquePtr(clang_type));
     switch (qual_type->getTypeClass())
     {
-    case clang::Type::FunctionNoProto:         break;
-    case clang::Type::FunctionProto:           break;
-    case clang::Type::IncompleteArray:         break;
-    case clang::Type::VariableArray:           break;
-    case clang::Type::ConstantArray:           break;
-    case clang::Type::ExtVector:               break;
-    case clang::Type::Vector:                  break;
-    case clang::Type::Builtin:                 break;
-    case clang::Type::ObjCObjectPointer:       break;
-    case clang::Type::BlockPointer:            break;
-    case clang::Type::Pointer:                 break;
-    case clang::Type::LValueReference:         break;
-    case clang::Type::RValueReference:         break;
-    case clang::Type::MemberPointer:           break;
-    case clang::Type::Complex:                 break;
-    case clang::Type::ObjCInterface:           break;
-    case clang::Type::Record:
-        return cast<RecordType>(qual_type)->getDecl();
-    case clang::Type::Enum:
-        return cast<EnumType>(qual_type)->getDecl();
-    case clang::Type::Typedef:
-        return ClangASTContext::GetDeclContextForType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr());
+    case clang::Type::FunctionNoProto:          break;
+    case clang::Type::FunctionProto:            break;
+    case clang::Type::IncompleteArray:          break;
+    case clang::Type::VariableArray:            break;
+    case clang::Type::ConstantArray:            break;
+    case clang::Type::ExtVector:                break;
+    case clang::Type::Vector:                   break;
+    case clang::Type::Builtin:                  break;
+    case clang::Type::BlockPointer:             break;
+    case clang::Type::Pointer:                  break;
+    case clang::Type::LValueReference:          break;
+    case clang::Type::RValueReference:          break;
+    case clang::Type::MemberPointer:            break;
+    case clang::Type::Complex:                  break;
+    case clang::Type::ObjCObject:               break;
+    case clang::Type::ObjCInterface:            return cast<ObjCObjectType>(qual_type.getTypePtr())->getInterface();
+    case clang::Type::ObjCObjectPointer:        return ClangASTContext::GetDeclContextForType (cast<ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr());
+    case clang::Type::Record:                   return cast<RecordType>(qual_type)->getDecl();
+    case clang::Type::Enum:                     return cast<EnumType>(qual_type)->getDecl();
+    case clang::Type::Typedef:                  return ClangASTContext::GetDeclContextForType (cast<TypedefType>(qual_type)->LookThroughTypedefs().getAsOpaquePtr());
 
-    case clang::Type::TypeOfExpr:              break;
-    case clang::Type::TypeOf:                  break;
-    case clang::Type::Decltype:                break;
-    //case clang::Type::QualifiedName:           break;
-    case clang::Type::TemplateSpecialization:  break;
+    case clang::Type::TypeOfExpr:               break;
+    case clang::Type::TypeOf:                   break;
+    case clang::Type::Decltype:                 break;
+    //case clang::Type::QualifiedName:          break;
+    case clang::Type::TemplateSpecialization:   break;
     }
     // No DeclContext in this type...
     return NULL;