Added a new enumeration named "ClangASTContext::AccessType" that abstracts the type creation from the various access enumerations in Clang. Currently there are clang::AccessSpecifier and the objective C ivars have their own enumeration. So I added a new enumeration that will allow a consistent interface when creating types through ClangASTContext.

I also added new functions to create an Objective C class, ivar and set an objective C superclass. They aren't hooked up in the DWARF parser yet. That is the next step, though I am unsure if I will do this in the DWARF parser or try and do it generically in the existing Record manipulation functions.

llvm-svn: 109130
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 866617b..ad8bb2c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -57,20 +57,17 @@
 using namespace lldb_private;
 
 
-static uint32_t
-DwarfToClangAccessibility (uint32_t dwarf_accessibility)
+static ClangASTContext::AccessType
+DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility)
 {
     switch (dwarf_accessibility)
     {
-        case DW_ACCESS_public:
-            return clang::AS_public;
-        case DW_ACCESS_private:
-            return clang::AS_private;
-        case DW_ACCESS_protected:
-            return clang::AS_protected;
-        default:
-            return clang::AS_none;
+        case DW_ACCESS_public:      return ClangASTContext::eAccessPublic;
+        case DW_ACCESS_private:     return ClangASTContext::eAccessPrivate;
+        case DW_ACCESS_protected:   return ClangASTContext::eAccessProtected;
+        default:                    break;
     }
+    return ClangASTContext::eAccessNone;
 }
 
 void
@@ -1216,7 +1213,7 @@
     const DWARFDebugInfoEntry *parent_die,
     std::vector<clang::CXXBaseSpecifier *>& base_classes,
     std::vector<int>& member_accessibilities,
-    int& default_accessibility,
+    ClangASTContext::AccessType& default_accessibility,
     bool &is_a_class
 )
 {
@@ -1243,7 +1240,7 @@
                     DWARFExpression location;
                     const char *name = NULL;
                     lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
-                    uint32_t accessibility = clang::AS_none;
+                    ClangASTContext::AccessType accessibility = ClangASTContext::eAccessNone;
                     off_t member_offset = 0;
                     size_t byte_size = 0;
                     size_t bit_offset = 0;
@@ -1280,7 +1277,7 @@
                                 }
                                 break;
 
-                            case DW_AT_accessibility: accessibility = DwarfToClangAccessibility (form_value.Unsigned()); break;
+                            case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType (form_value.Unsigned()); break;
                             case DW_AT_declaration:
                             case DW_AT_description:
                             case DW_AT_mutable:
@@ -1294,7 +1291,7 @@
 
                     Type *member_type = ResolveTypeUID(encoding_uid);
                     assert(member_type);
-                    if (accessibility == clang::AS_none)
+                    if (accessibility == ClangASTContext::eAccessNone)
                         accessibility = default_accessibility;
                     member_accessibilities.push_back(accessibility);
 
@@ -1306,8 +1303,8 @@
         case DW_TAG_subprogram:
             {
                 is_a_class = true;
-                if (default_accessibility == clang::AS_none)
-                    default_accessibility = clang::AS_private;
+                if (default_accessibility == ClangASTContext::eAccessNone)
+                    default_accessibility = ClangASTContext::eAccessPrivate;
                 // TODO: implement DW_TAG_subprogram type parsing
 //              UserDefTypeChildInfo method_info(die->GetOffset());
 //
@@ -1323,8 +1320,8 @@
         case DW_TAG_inheritance:
             {
                 is_a_class = true;
-                if (default_accessibility == clang::AS_none)
-                    default_accessibility = clang::AS_private;
+                if (default_accessibility == ClangASTContext::eAccessNone)
+                    default_accessibility = ClangASTContext::eAccessPrivate;
                 // TODO: implement DW_TAG_inheritance type parsing
                 DWARFDebugInfoEntry::Attributes attributes;
                 const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes);
@@ -1333,7 +1330,7 @@
                     Declaration decl;
                     DWARFExpression location;
                     lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
-                    uint32_t accessibility = default_accessibility;
+                    ClangASTContext::AccessType accessibility = default_accessibility;
                     bool is_virtual = false;
                     bool is_base_of_class = true;
                     off_t member_offset = 0;
@@ -1366,7 +1363,7 @@
                                 break;
 
                             case DW_AT_accessibility:
-                                accessibility = DwarfToClangAccessibility(form_value.Unsigned());
+                                accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
                                 break;
 
                             case DW_AT_virtuality: is_virtual = form_value.Unsigned() != 0; break;
@@ -2574,7 +2571,7 @@
 {
     TypeSP type_sp;
 
-    uint32_t accessibility = clang::AS_none;
+    ClangASTContext::AccessType accessibility = ClangASTContext::eAccessNone;
     if (die != NULL)
     {
         dw_tag_t tag = die->Tag();
@@ -2732,7 +2729,7 @@
                                     type_name_dbstr.SetCString(type_name_cstr);
                                     break;
                                 case DW_AT_byte_size:   byte_size = form_value.Unsigned(); break;
-                                case DW_AT_accessibility: accessibility = DwarfToClangAccessibility(form_value.Unsigned()); break; break;
+                                case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; break;
                                 case DW_AT_declaration: is_forward_declaration = form_value.Unsigned() != 0; break;
                                 case DW_AT_allocated:
                                 case DW_AT_associated:
@@ -2749,21 +2746,21 @@
                     }
 
                     int tag_decl_kind = -1;
-                    int default_accessibility = clang::AS_none;
+                    ClangASTContext::AccessType default_accessibility = ClangASTContext::eAccessNone;
                     if (tag == DW_TAG_structure_type)
                     {
                         tag_decl_kind = clang::TTK_Struct;
-                        default_accessibility = clang::AS_public;
+                        default_accessibility = ClangASTContext::eAccessPublic;
                     }
                     else if (tag == DW_TAG_union_type)
                     {
                         tag_decl_kind = clang::TTK_Union;
-                        default_accessibility = clang::AS_public;
+                        default_accessibility = ClangASTContext::eAccessPublic;
                     }
                     else if (tag == DW_TAG_class_type)
                     {
                         tag_decl_kind = clang::TTK_Class;
-                        default_accessibility = clang::AS_private;
+                        default_accessibility = ClangASTContext::eAccessPrivate;
                     }
 
                     assert (tag_decl_kind != -1);
@@ -2804,7 +2801,7 @@
                         {
                             // This is a class and all members that didn't have
                             // their access specified are private.
-                            type_list->GetClangASTContext().SetDefaultAccessForRecordFields (clang_type, clang::AS_private, &member_accessibilities.front(), member_accessibilities.size());
+                            type_list->GetClangASTContext().SetDefaultAccessForRecordFields (clang_type, ClangASTContext::eAccessPrivate, &member_accessibilities.front(), member_accessibilities.size());
                         }
 
                         if (!base_classes.empty())
@@ -2853,7 +2850,7 @@
                                     break;
                                 case DW_AT_type:        encoding_uid = form_value.Reference(dwarf_cu); break;
                                 case DW_AT_byte_size:   byte_size = form_value.Unsigned(); break;
-                                case DW_AT_accessibility: accessibility = DwarfToClangAccessibility(form_value.Unsigned()); break;
+                                case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
                                 case DW_AT_declaration: is_forward_declaration = form_value.Unsigned() != 0; break;
                                 case DW_AT_allocated:
                                 case DW_AT_associated:
@@ -2926,7 +2923,7 @@
 
                                 case DW_AT_MIPS_linkage_name:   mangled = form_value.AsCString(&get_debug_str_data()); break;
                                 case DW_AT_type:                type_die_offset = form_value.Reference(dwarf_cu); break;
-                                case DW_AT_accessibility:       accessibility = DwarfToClangAccessibility(form_value.Unsigned()); break;
+                                case DW_AT_accessibility:       accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
                                 case DW_AT_declaration:         is_forward_declaration = form_value.Unsigned() != 0; break;
                                 case DW_AT_external:
                                     if (form_value.Unsigned())
@@ -3043,7 +3040,7 @@
                                 case DW_AT_byte_size:       byte_size = form_value.Unsigned(); break;
                                 case DW_AT_byte_stride:     byte_stride = form_value.Unsigned(); break;
                                 case DW_AT_bit_stride:      bit_stride = form_value.Unsigned(); break;
-                                case DW_AT_accessibility:   accessibility = DwarfToClangAccessibility(form_value.Unsigned()); break;
+                                case DW_AT_accessibility:   accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
                                 case DW_AT_declaration:     is_forward_declaration = form_value.Unsigned() != 0; break;
                                 case DW_AT_allocated:
                                 case DW_AT_associated:
@@ -3366,7 +3363,7 @@
         DWARFExpression location;
         bool is_external = false;
         bool is_artificial = false;
-        uint32_t accessibility = clang::AS_none;
+        ClangASTContext::AccessType accessibility = ClangASTContext::eAccessNone;
 
         for (i=0; i<num_attributes; ++i)
         {
@@ -3408,7 +3405,7 @@
                     break;
 
                 case DW_AT_artificial:      is_artificial = form_value.Unsigned() != 0; break;
-                case DW_AT_accessibility:   accessibility = DwarfToClangAccessibility(form_value.Unsigned()); break;
+                case DW_AT_accessibility:   accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
                 case DW_AT_const_value:
                 case DW_AT_declaration:
                 case DW_AT_description:
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index f2a507ca..a5acdd5 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -25,6 +25,7 @@
 #include "lldb/Core/DataExtractor.h"
 #include "lldb/Core/Flags.h"
 #include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/SymbolFile.h"
 #include "lldb/Symbol/SymbolContext.h"
 
@@ -250,7 +251,7 @@
                                 const DWARFDebugInfoEntry *die,
                                 std::vector<clang::CXXBaseSpecifier *>& base_classes,
                                 std::vector<int>& member_accessibilities,
-                                int &default_accessibility,
+                                lldb_private::ClangASTContext::AccessType &default_accessibility,
                                 bool &is_a_class);
 
     size_t                  ParseChildParameters(
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index 7216565..3d6d61e 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/lldb/source/Symbol/ClangASTContext.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTImporter.h"
 #include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/Builtins.h"
@@ -37,6 +38,36 @@
 using namespace llvm;
 using namespace clang;
 
+static AccessSpecifier
+ConvertAccessTypeToAccessSpecifier (ClangASTContext::AccessType access)
+{
+    switch (access)
+    {
+    default:                                break;
+    case ClangASTContext::eAccessNone:      return AS_none;
+    case ClangASTContext::eAccessPublic:    return AS_public;
+    case ClangASTContext::eAccessPrivate:   return AS_private;
+    case ClangASTContext::eAccessProtected: return AS_protected;
+    }
+    return AS_none;
+}
+
+static ObjCIvarDecl::AccessControl
+ConvertAccessTypeToObjCIvarAccessControl (ClangASTContext::AccessType access)
+{
+    switch (access)
+    {
+    default:                                break;
+    case ClangASTContext::eAccessNone:      return ObjCIvarDecl::None;
+    case ClangASTContext::eAccessPublic:    return ObjCIvarDecl::Public;
+    case ClangASTContext::eAccessPrivate:   return ObjCIvarDecl::Private;
+    case ClangASTContext::eAccessProtected: return ObjCIvarDecl::Protected;
+    case ClangASTContext::eAccessPackage:   return ObjCIvarDecl::Package;
+    }
+    return ObjCIvarDecl::None;
+}
+
+
 static void
 ParseLangArgs
 (
@@ -661,7 +692,7 @@
 void *
 ClangASTContext::CopyType(clang::ASTContext *dest_context, 
                           clang::ASTContext *source_context,
-                          void * clang_type)
+                          void *clang_type)
 {
     Diagnostic diagnostics;
     FileManager file_manager;
@@ -745,7 +776,14 @@
 }
 
 bool
-ClangASTContext::AddFieldToRecordType (void * record_clang_type, const char *name, void * field_type, int access, uint32_t bitfield_bit_size)
+ClangASTContext::AddFieldToRecordType 
+(
+    void *record_clang_type, 
+    const char *name, 
+    void *field_type, 
+    AccessType access, 
+    uint32_t bitfield_bit_size
+)
 {
     if (record_clang_type == NULL || field_type == NULL)
         return false;
@@ -777,16 +815,16 @@
                 APInt bitfield_bit_size_apint(ast_context->getTypeSize(ast_context->IntTy), bitfield_bit_size);
                 bit_width = new (*ast_context)IntegerLiteral (bitfield_bit_size_apint, ast_context->IntTy, SourceLocation());
             }
-            FieldDecl *field = FieldDecl::Create(*ast_context,
-                                                record_decl,
-                                                SourceLocation(),
-                                                name ? &identifier_table->get(name) : NULL, // Identifier
-                                                QualType::getFromOpaquePtr(field_type), // Field type
-                                                NULL,       // DeclaratorInfo *
-                                                bit_width,  // BitWidth
-                                                false);     // Mutable
+            FieldDecl *field = FieldDecl::Create (*ast_context,
+                                                  record_decl,
+                                                  SourceLocation(),
+                                                  name ? &identifier_table->get(name) : NULL, // Identifier
+                                                  QualType::getFromOpaquePtr(field_type), // Field type
+                                                  NULL,       // DeclaratorInfo *
+                                                  bit_width,  // BitWidth
+                                                  false);     // Mutable
 
-            field->setAccess((AccessSpecifier)access);
+            field->setAccess (ConvertAccessTypeToAccessSpecifier (access));
 
             if (field)
             {
@@ -891,7 +929,7 @@
 #pragma mark C++ Base Classes
 
 CXXBaseSpecifier *
-ClangASTContext::CreateBaseClassSpecifier (void *base_class_type, int access, bool is_virtual, bool base_of_class)
+ClangASTContext::CreateBaseClassSpecifier (void *base_class_type, AccessType access, bool is_virtual, bool base_of_class)
 {
     if (base_class_type)
         return new CXXBaseSpecifier(SourceRange(), is_virtual, base_of_class, (AccessSpecifier)access, QualType::getFromOpaquePtr(base_class_type));
@@ -931,7 +969,128 @@
     }
     return false;
 }
+#pragma mark Objective C Classes
 
+void *
+ClangASTContext::CreateObjCClass 
+(
+    const char *name, 
+    DeclContext *decl_ctx, 
+    bool isForwardDecl, 
+    bool isInternal
+)
+{
+    ASTContext *ast_context = getASTContext();
+    assert (ast_context != NULL);
+    assert (name && name[0]);
+    if (decl_ctx == NULL)
+        decl_ctx = ast_context->getTranslationUnitDecl();
+
+    // 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
+    // if something is struct or a class, so we default to always use the more
+    // complete definition just in case.
+    ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create (*ast_context,
+                                                         decl_ctx,
+                                                         SourceLocation(),
+                                                         &ast_context->Idents.get(name),
+                                                         SourceLocation(),
+                                                         isForwardDecl,
+                                                         isInternal);
+
+    return QualType (decl->getTypeForDecl(), 0).getAsOpaquePtr();
+}
+
+bool
+ClangASTContext::SetObjCSuperClass (void *class_opaque_type, void *super_opaque_type)
+{
+    if (class_opaque_type && super_opaque_type)
+    {
+        QualType class_qual_type(QualType::getFromOpaquePtr(class_opaque_type));
+        QualType super_qual_type(QualType::getFromOpaquePtr(super_opaque_type));
+        clang::Type *class_type = class_qual_type.getTypePtr();
+        clang::Type *super_type = super_qual_type.getTypePtr();
+        if (class_type && super_type)
+        {
+            ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(class_type);
+            ObjCObjectType *objc_super_type = dyn_cast<ObjCObjectType>(super_type);
+            if (objc_class_type && objc_super_type)
+            {
+                ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+                ObjCInterfaceDecl *super_interface_decl = objc_super_type->getInterface();
+                if (class_interface_decl && super_interface_decl)
+                {
+                    class_interface_decl->setSuperClass(super_interface_decl);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+
+bool
+ClangASTContext::AddObjCClassIVar 
+(
+    void *class_opaque_type, 
+    const char *name, 
+    void *ivar_opaque_type, 
+    AccessType access, 
+    uint32_t bitfield_bit_size, 
+    bool isSynthesized
+)
+{
+    if (class_opaque_type == NULL || ivar_opaque_type == NULL)
+        return false;
+
+    ASTContext *ast_context = getASTContext();
+    IdentifierTable *identifier_table = getIdentifierTable();
+
+    assert (ast_context != NULL);
+    assert (identifier_table != NULL);
+
+    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)
+        {
+            ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+            
+            if (class_interface_decl)
+            {
+                clang::Expr *bit_width = NULL;
+                if (bitfield_bit_size != 0)
+                {
+                    APInt bitfield_bit_size_apint(ast_context->getTypeSize(ast_context->IntTy), bitfield_bit_size);
+                    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;
+            }
+        }
+    }
+    return false;
+}
 
 #pragma mark Aggregate Types
 
@@ -1956,7 +2115,7 @@
 }
 
 ParmVarDecl *
-ClangASTContext::CreateParmeterDeclaration (const char *name, void * return_type, int storage)
+ClangASTContext::CreateParmeterDeclaration (const char *name, void *return_type, int storage)
 {
     ASTContext *ast_context = getASTContext();
     assert (ast_context != NULL);
@@ -2147,7 +2306,7 @@
 }
 
 void *
-ClangASTContext::CreateMemberPointerType (void * clang_pointee_type, void * clang_class_type)
+ClangASTContext::CreateMemberPointerType (void *clang_pointee_type, void *clang_class_type)
 {
     if (clang_pointee_type && clang_pointee_type)
         return getASTContext()->getMemberPointerType(QualType::getFromOpaquePtr(clang_pointee_type),
@@ -2220,7 +2379,7 @@
 }
 
 bool
-ClangASTContext::IsIntegerType (void * clang_type, bool &is_signed)
+ClangASTContext::IsIntegerType (void *clang_type, bool &is_signed)
 {
     if (!clang_type)
         return false;
@@ -2376,7 +2535,7 @@
 }
 
 bool
-ClangASTContext::IsArrayType (void * clang_type, void **member_type, uint64_t *size)
+ClangASTContext::IsArrayType (void *clang_type, void **member_type, uint64_t *size)
 {
     if (!clang_type)
         return false;