diff --git a/lldb/include/lldb/Core/Language.h b/lldb/include/lldb/Core/Language.h index b5830796a5d6..711fc63b1a09 100644 --- a/lldb/include/lldb/Core/Language.h +++ b/lldb/include/lldb/Core/Language.h @@ -26,42 +26,10 @@ namespace lldb_private { class Language { public: - - //------------------------------------------------------------------ - /// Programming language type. - /// - /// These enumerations use the same language enumerations as the - /// DWARF specification for ease of use and consistency. - //------------------------------------------------------------------ - typedef enum - { - Unknown = 0x0000, ///< Unknown or invalid language value. - C89 = 0x0001, ///< ISO C:1989. - C = 0x0002, ///< Non-standardized C, such as K&R. - Ada83 = 0x0003, ///< ISO Ada:1983. - C_plus_plus = 0x0004, ///< ISO C++:1998. - Cobol74 = 0x0005, ///< ISO Cobol:1974. - Cobol85 = 0x0006, ///< ISO Cobol:1985. - Fortran77 = 0x0007, ///< ISO Fortran 77. - Fortran90 = 0x0008, ///< ISO Fortran 90. - Pascal83 = 0x0009, ///< ISO Pascal:1983. - Modula2 = 0x000a, ///< ISO Modula-2:1996. - Java = 0x000b, ///< Java. - C99 = 0x000c, ///< ISO C:1999. - Ada95 = 0x000d, ///< ISO Ada:1995. - Fortran95 = 0x000e, ///< ISO Fortran 95. - PLI = 0x000f, ///< ANSI PL/I:1976. - ObjC = 0x0010, ///< Objective-C. - ObjC_plus_plus = 0x0011, ///< Objective-C++. - UPC = 0x0012, ///< Unified Parallel C. - D = 0x0013, ///< D. - Python = 0x0014 ///< Python. - } Type; - //------------------------------------------------------------------ /// Construct with optional language enumeration. //------------------------------------------------------------------ - Language(Language::Type language = Unknown); + Language(lldb::LanguageType language = lldb::eLanguageTypeUnknown); //------------------------------------------------------------------ /// Destructor. @@ -78,7 +46,7 @@ public: /// The C string representation of the language. The returned /// string does not need to be freed as it comes from constant /// strings. NULL can be returned when the language is set to - /// a value that doesn't match of of the Language::Type + /// a value that doesn't match of of the lldb::LanguageType /// enumerations. //------------------------------------------------------------------ const char * @@ -106,7 +74,7 @@ public: /// The enumeration value that describes the programming /// language that an object is associated with. //------------------------------------------------------------------ - Language::Type + lldb::LanguageType GetLanguage() const; //------------------------------------------------------------------ @@ -117,7 +85,7 @@ public: /// language that an object is associated with. //------------------------------------------------------------------ void - SetLanguage(Language::Type language); + SetLanguage(lldb::LanguageType language); //------------------------------------------------------------------ /// Set accessor for the language. @@ -133,9 +101,9 @@ protected: //------------------------------------------------------------------ // Member variables //------------------------------------------------------------------ - Language::Type m_language; ///< The programming language enumeration value. - ///< The enumeration values are the same as the - ///< latest DWARF specification. + lldb::LanguageType m_language; ///< The programming language enumeration value. + ///< The enumeration values are the same as the + ///< latest DWARF specification. }; //-------------------------------------------------------------- diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h index b3e6b4ea487b..05dc8eecb2c7 100644 --- a/lldb/include/lldb/Symbol/ClangASTContext.h +++ b/lldb/include/lldb/Symbol/ClangASTContext.h @@ -157,7 +157,8 @@ public: void * CreateRecordType (const char *name, int kind, - clang::DeclContext *decl_ctx); + clang::DeclContext *decl_ctx, + lldb::LanguageType language); bool AddFieldToRecordType (void * record_qual_type, @@ -201,6 +202,14 @@ public: bool SetObjCSuperClass (void *class_clang_type, void *superclass_clang_type); + + static bool + ObjCTypeHasIVars (void *class_clang_type, bool check_superclass); + + static bool + ObjCDeclHasIVars (clang::ObjCInterfaceDecl *class_interface_decl, + bool check_superclass); + //------------------------------------------------------------------ // Aggregate Types diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h index 779363fd8b70..e8c06fa653ec 100644 --- a/lldb/include/lldb/Symbol/CompileUnit.h +++ b/lldb/include/lldb/Symbol/CompileUnit.h @@ -66,9 +66,9 @@ public: /// A language enumeration type that describes the main language /// of this compile unit. /// - /// @see Language::Type + /// @see lldb::LanguageType //------------------------------------------------------------------ - CompileUnit(Module *module, void *user_data, const char *pathname, lldb::user_id_t uid, Language::Type language); + CompileUnit(Module *module, void *user_data, const char *pathname, lldb::user_id_t uid, lldb::LanguageType language); //------------------------------------------------------------------ /// Construct with a module, file spec, UID and language. @@ -98,9 +98,9 @@ public: /// A language enumeration type that describes the main language /// of this compile unit. /// - /// @see Language::Type + /// @see lldb::LanguageType //------------------------------------------------------------------ - CompileUnit(Module *module, void *user_data, const FileSpec &file_spec, lldb::user_id_t uid, Language::Type language); + CompileUnit(Module *module, void *user_data, const FileSpec &file_spec, lldb::user_id_t uid, lldb::LanguageType language); //------------------------------------------------------------------ /// Destructor diff --git a/lldb/include/lldb/Symbol/SymbolContext.h b/lldb/include/lldb/Symbol/SymbolContext.h index 72e15ad866b4..1ecc340cc644 100644 --- a/lldb/include/lldb/Symbol/SymbolContext.h +++ b/lldb/include/lldb/Symbol/SymbolContext.h @@ -225,7 +225,7 @@ public: //------------------------------------------------------------------ // Member variables //------------------------------------------------------------------ - lldb::TargetSP target_sp; ///< The Target for a given query + lldb::TargetSP target_sp; ///< The Target for a given query lldb::ModuleSP module_sp; ///< The Module for a given query CompileUnit * comp_unit; ///< The CompileUnit for a given query Function * function; ///< The Function for a given query diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index af4b88be43d1..f93f9606c9ef 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -428,6 +428,38 @@ typedef enum BreakpointEventType } BreakpointEventType; +//---------------------------------------------------------------------- +/// Programming language type. +/// +/// These enumerations use the same language enumerations as the DWARF +/// specification for ease of use and consistency. +//---------------------------------------------------------------------- +typedef enum LanguageType +{ + eLanguageTypeUnknown = 0x0000, ///< Unknown or invalid language value. + eLanguageTypeC89 = 0x0001, ///< ISO C:1989. + eLanguageTypeC = 0x0002, ///< Non-standardized C, such as K&R. + eLanguageTypeAda83 = 0x0003, ///< ISO Ada:1983. + eLanguageTypeC_plus_plus = 0x0004, ///< ISO C++:1998. + eLanguageTypeCobol74 = 0x0005, ///< ISO Cobol:1974. + eLanguageTypeCobol85 = 0x0006, ///< ISO Cobol:1985. + eLanguageTypeFortran77 = 0x0007, ///< ISO Fortran 77. + eLanguageTypeFortran90 = 0x0008, ///< ISO Fortran 90. + eLanguageTypePascal83 = 0x0009, ///< ISO Pascal:1983. + eLanguageTypeModula2 = 0x000a, ///< ISO Modula-2:1996. + eLanguageTypeJava = 0x000b, ///< Java. + eLanguageTypeC99 = 0x000c, ///< ISO C:1999. + eLanguageTypeAda95 = 0x000d, ///< ISO Ada:1995. + eLanguageTypeFortran95 = 0x000e, ///< ISO Fortran 95. + eLanguageTypePLI = 0x000f, ///< ANSI PL/I:1976. + eLanguageTypeObjC = 0x0010, ///< Objective-C. + eLanguageTypeObjC_plus_plus = 0x0011, ///< Objective-C++. + eLanguageTypeUPC = 0x0012, ///< Unified Parallel C. + eLanguageTypeD = 0x0013, ///< D. + eLanguageTypePython = 0x0014 ///< Python. +} LanguageType; + + } // namespace lldb diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 0db3c3a68186..e04b8eef3898 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -146,21 +146,21 @@ public: "'alias' allows the user to create a short-cut or abbreviation for long \n\ commands, multi-word commands, and commands that take particular options. \n\ Below are some simple examples of how one might use the 'alias' command: \n\ - \n 'alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\ + \n 'command alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\ // command. \n\ - 'alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\ + 'command alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\ // command. Since breakpoint commands are two-word \n\ // commands, the user will still need to enter the \n\ // second word after 'bp', e.g. 'bp enable' or \n\ // 'bp delete'. \n\ - 'alias bpi breakpoint list' // Creates the abbreviation 'bpi' for the \n\ + 'command alias bpi breakpoint list' // Creates the abbreviation 'bpi' for the \n\ // two-word command 'breakpoint list'. \n\ \nAn alias can include some options for the command, with the values either \n\ filled in at the time the alias is created, or specified as positional \n\ arguments, to be filled in when the alias is invoked. The following example \n\ shows how to create aliases with options: \n\ \n\ - 'alias bfl breakpoint set -f %1 -l %2' \n\ + 'command alias bfl breakpoint set -f %1 -l %2' \n\ \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\ options already part of the alias. So if the user wants to set a breakpoint \n\ by file and line without explicitly having to use the -f and -l options, the \n\ diff --git a/lldb/source/Core/Language.cpp b/lldb/source/Core/Language.cpp index add2a22d66cb..af62af37da0d 100644 --- a/lldb/source/Core/Language.cpp +++ b/lldb/source/Core/Language.cpp @@ -51,7 +51,7 @@ g_languages[] = static const size_t g_num_languages = sizeof(g_languages)/sizeof(LanguageStrings); -Language::Language(Language::Type language) : +Language::Language(LanguageType language) : m_language (language) { } @@ -60,7 +60,7 @@ Language::~Language() { } -Language::Type +LanguageType Language::GetLanguage() const { return m_language; @@ -69,11 +69,11 @@ Language::GetLanguage() const void Language::Clear () { - m_language = Unknown; + m_language = eLanguageTypeUnknown; } void -Language::SetLanguage(Language::Type language) +Language::SetLanguage(LanguageType language) { m_language = language; } @@ -95,13 +95,13 @@ Language::SetLanguageFromCString(const char *language_cstr) if (::strcasecmp (language_cstr, name) == 0) { - m_language = (Language::Type)i; + m_language = (LanguageType)i; return true; } } } - m_language = Unknown; + m_language = eLanguageTypeUnknown; return false; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index ad8bb2c677bc..ebd0e5085406 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -644,12 +644,12 @@ SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit* cu, CompUnitSP& compile_unit { const char * cu_die_name = cu_die->GetName(this, cu); const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, cu, DW_AT_comp_dir, NULL); - Language::Type language = (Language::Type)cu_die->GetAttributeValueAsUnsigned(this, cu, DW_AT_language, 0); + LanguageType class_language = (LanguageType)cu_die->GetAttributeValueAsUnsigned(this, cu, DW_AT_language, 0); if (cu_die_name) { if (cu_die_name[0] == '/' || cu_comp_dir == NULL && cu_comp_dir[0]) { - compile_unit_sp.reset(new CompileUnit(m_obj_file->GetModule(), cu, cu_die_name, cu->GetOffset(), language)); + compile_unit_sp.reset(new CompileUnit(m_obj_file->GetModule(), cu, cu_die_name, cu->GetOffset(), class_language)); } else { @@ -658,7 +658,7 @@ SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit* cu, CompUnitSP& compile_unit fullpath += '/'; fullpath += cu_die_name; - compile_unit_sp.reset(new CompileUnit(m_obj_file->GetModule(), cu, fullpath.c_str(), cu->GetOffset(), language)); + compile_unit_sp.reset(new CompileUnit(m_obj_file->GetModule(), cu, fullpath.c_str(), cu->GetOffset(), class_language)); } if (compile_unit_sp.get()) @@ -1211,6 +1211,8 @@ SymbolFileDWARF::ParseChildMembers TypeSP& type_sp, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *parent_die, + void *class_clang_type, + const LanguageType class_language, std::vector& base_classes, std::vector& member_accessibilities, ClangASTContext::AccessType& default_accessibility, @@ -1376,8 +1378,16 @@ SymbolFileDWARF::ParseChildMembers Type *base_class_dctype = ResolveTypeUID(encoding_uid); assert(base_class_dctype); - base_classes.push_back (type_list->GetClangASTContext().CreateBaseClassSpecifier (base_class_dctype->GetOpaqueClangQualType(), accessibility, is_virtual, is_base_of_class)); - assert(base_classes.back()); + + if (class_language == eLanguageTypeObjC) + { + type_list->GetClangASTContext().SetObjCSuperClass(class_clang_type, base_class_dctype->GetOpaqueClangQualType()); + } + else + { + base_classes.push_back (type_list->GetClangASTContext().CreateBaseClassSpecifier (base_class_dctype->GetOpaqueClangQualType(), accessibility, is_virtual, is_base_of_class)); + assert(base_classes.back()); + } } } break; @@ -2707,6 +2717,7 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar const_cast(die)->SetUserData(DIE_IS_BEING_PARSED); size_t byte_size = 0; + LanguageType class_language = eLanguageTypeUnknown; //bool struct_is_class = false; Declaration decl; const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes); @@ -2721,16 +2732,39 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar { switch (attr) { - case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; - case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break; - case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; + case DW_AT_decl_file: + decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); + break; + + case DW_AT_decl_line: + decl.SetLine(form_value.Unsigned()); + break; + + case DW_AT_decl_column: + decl.SetColumn(form_value.Unsigned()); + break; + case DW_AT_name: type_name_cstr = form_value.AsCString(&get_debug_str_data()); type_name_dbstr.SetCString(type_name_cstr); break; - case DW_AT_byte_size: byte_size = form_value.Unsigned(); 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_byte_size: + byte_size = 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_APPLE_runtime_class: + class_language = (LanguageType)form_value.Signed(); + break; + case DW_AT_allocated: case DW_AT_associated: case DW_AT_data_location: @@ -2764,7 +2798,7 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar } assert (tag_decl_kind != -1); - clang_type = type_list->GetClangASTContext().CreateRecordType (type_name_cstr, tag_decl_kind, GetClangDeclContextForDIE (dwarf_cu, die)); + clang_type = type_list->GetClangASTContext().CreateRecordType (type_name_cstr, tag_decl_kind, GetClangDeclContextForDIE (dwarf_cu, die), class_language); m_die_to_decl_ctx[die] = ClangASTContext::GetDeclContextForType (clang_type); type_sp.reset( new Type(die->GetOffset(), this, type_name_dbstr, byte_size, NULL, LLDB_INVALID_UID, Type::eIsTypeWithUID, &decl, clang_type)); @@ -2781,11 +2815,24 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar std::vector base_classes; std::vector member_accessibilities; bool is_a_class = false; - ParseChildMembers(sc, type_sp, dwarf_cu, die, base_classes, member_accessibilities, default_accessibility, is_a_class); + ParseChildMembers (sc, + type_sp, + dwarf_cu, + die, + clang_type, + class_language, + base_classes, + member_accessibilities, + default_accessibility, + is_a_class); + // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we // need to tell the clang type it is actually a class. - if (is_a_class && tag_decl_kind != clang::TTK_Class) - type_list->GetClangASTContext().SetTagTypeKind (clang_type, clang::TTK_Class); + if (class_language != eLanguageTypeObjC) + { + if (is_a_class && tag_decl_kind != clang::TTK_Class) + type_list->GetClangASTContext().SetTagTypeKind (clang_type, clang::TTK_Class); + } // Since DW_TAG_structure_type gets used for both classes // and structures, we may need to set any DW_TAG_member diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index a5acdd5dd400..7a9cd9cd42f1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -249,6 +249,8 @@ protected: lldb::TypeSP& type_sp, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, + void *class_clang_type, + const lldb::LanguageType class_language, std::vector& base_classes, std::vector& member_accessibilities, lldb_private::ClangASTContext::AccessType &default_accessibility, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 9da672f948bc..e760329034d4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -495,7 +495,7 @@ SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) NULL, so_symbol->GetMangled().GetName().AsCString(), cu_idx, - Language::Unknown)); + eLanguageTypeUnknown)); } } } diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index ff7b8bf742ae..a6d58f605556 100644 --- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -140,14 +140,14 @@ SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) { const FileSpec &obj_file_spec = m_obj_file->GetFileSpec(); if (obj_file_spec) - cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, obj_file_spec, 0, Language::Unknown)); + cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, obj_file_spec, 0, eLanguageTypeUnknown)); } else if (idx < m_source_indexes.size()) { const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); if (cu_symbol) - cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, cu_symbol->GetMangled().GetName().AsCString(), 0, Language::Unknown)); + cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, cu_symbol->GetMangled().GetName().AsCString(), 0, eLanguageTypeUnknown)); } return cu_sp; } diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 3b1d9c8de521..52235dab2409 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -753,7 +753,7 @@ ClangASTContext::AddVolatileModifier (void *clang_type) #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 @@ ClangASTContext::CreateRecordType (const char *name, int kind, DeclContext *decl 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 @@ ClangASTContext::AddFieldToRecordType return true; } } + else + { + ObjCObjectType *objc_class_type = dyn_cast(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 @@ ClangASTContext::CreateObjCClass SourceLocation(), isForwardDecl, isInternal); - - return QualType (decl->getTypeForDecl(), 0).getAsOpaquePtr(); + + return ast_context->getObjCInterfaceType(decl).getAsOpaquePtr(); } bool @@ -1071,27 +1093,61 @@ ClangASTContext::AddObjCClassIVar 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(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 @@ ClangASTContext::IsAggregateType (void *clang_type) 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 @@ ClangASTContext::GetNumChildren (void *clang_qual_type, bool omit_empty_base_cla 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 @@ ClangASTContext::GetNumChildren (void *clang_qual_type, bool omit_empty_base_cla } break; + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + { + ObjCObjectType *objc_class_type = dyn_cast(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(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr(), + omit_empty_base_classes); + case clang::Type::ConstantArray: num_children = cast(qual_type.getTypePtr())->getSize().getLimitedValue(); break; @@ -1184,7 +1278,8 @@ ClangASTContext::GetNumChildren (void *clang_qual_type, bool omit_empty_base_cla { PointerType *pointer_type = cast(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 @@ ClangASTContext::GetChildClangTypeAtIndex } break; + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + { + ObjCObjectType *objc_class_type = dyn_cast(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 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 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(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(parent_qual_type.getTypePtr()); @@ -1707,6 +1896,76 @@ ClangASTContext::GetIndexOfChildMemberWithName } break; + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + { + StringRef name_sref(name); + ObjCObjectType *objc_class_type = dyn_cast(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(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr(), + name, + omit_empty_base_classes, + child_indexes); + } + break; + + case clang::Type::ConstantArray: { // const ConstantArrayType *array = cast(parent_qual_type.getTypePtr()); @@ -1824,7 +2083,10 @@ ClangASTContext::GetIndexOfChildWithName 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 @@ ClangASTContext::GetIndexOfChildWithName } break; + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + { + StringRef name_sref(name); + ObjCObjectType *objc_class_type = dyn_cast(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(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr(), + name, + omit_empty_base_classes); + } + break; + case clang::Type::ConstantArray: { // const ConstantArrayType *array = cast(parent_qual_type.getTypePtr()); @@ -2003,34 +2314,32 @@ ClangASTContext::GetDeclContextForType (void *clang_type) 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(qual_type)->getDecl(); - case clang::Type::Enum: - return cast(qual_type)->getDecl(); - case clang::Type::Typedef: - return ClangASTContext::GetDeclContextForType (cast(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(qual_type.getTypePtr())->getInterface(); + case clang::Type::ObjCObjectPointer: return ClangASTContext::GetDeclContextForType (cast(qual_type.getTypePtr())->getPointeeType().getAsOpaquePtr()); + case clang::Type::Record: return cast(qual_type)->getDecl(); + case clang::Type::Enum: return cast(qual_type)->getDecl(); + case clang::Type::Typedef: return ClangASTContext::GetDeclContextForType (cast(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; diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp index 6c831db5e35b..615d7145e011 100644 --- a/lldb/source/Symbol/ClangASTType.cpp +++ b/lldb/source/Symbol/ClangASTType.cpp @@ -614,7 +614,8 @@ ClangASTType::DumpTypeValue } else { - switch (qual_type->getTypeClass()) + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { case clang::Type::Enum: { diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp index 7c60c1b9841b..eaf12110a0f7 100644 --- a/lldb/source/Symbol/CompileUnit.cpp +++ b/lldb/source/Symbol/CompileUnit.cpp @@ -16,7 +16,7 @@ using namespace lldb; using namespace lldb_private; -CompileUnit::CompileUnit (Module *module, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, Language::Type language) : +CompileUnit::CompileUnit (Module *module, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, lldb::LanguageType language) : ModuleChild(module), FileSpec (pathname), UserID(cu_sym_id), @@ -31,7 +31,7 @@ CompileUnit::CompileUnit (Module *module, void *user_data, const char *pathname, assert(module != NULL); } -CompileUnit::CompileUnit (Module *module, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, Language::Type language) : +CompileUnit::CompileUnit (Module *module, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, lldb::LanguageType language) : ModuleChild(module), FileSpec (fspec), UserID(cu_sym_id), diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 15604e3c66e4..845671ca2662 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -219,7 +219,7 @@ lldb_private::Type::Dump (Stream *s, bool show_context) const clang::TypedefDecl *typedef_decl = typedef_type->getDecl(); std::string clang_typedef_name (typedef_decl->getQualifiedNameAsString()); if (!clang_typedef_name.empty()) - *s << " (" << clang_typedef_name.c_str() << ')'; + *s << '(' << clang_typedef_name.c_str() << ')'; } else { @@ -229,7 +229,7 @@ lldb_private::Type::Dump (Stream *s, bool show_context) { std::string clang_type_name(qual_type.getAsString()); if (!clang_type_name.empty()) - *s << " (" << clang_type_name.c_str() << ')'; + *s << '(' << clang_type_name.c_str() << ')'; } } }