diff options
30 files changed, 627 insertions, 132 deletions
diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index 566d9e59ddf..c64e7b80eb2 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -492,6 +492,12 @@ public: SetNeedsUpdate (); virtual ~ValueObject(); + + clang::ASTContext * + GetClangAST (); + + lldb::clang_type_t + GetClangType (); //------------------------------------------------------------------ // Sublasses must implement the functions below. @@ -499,12 +505,6 @@ public: virtual size_t GetByteSize() = 0; - virtual clang::ASTContext * - GetClangAST () = 0; - - virtual lldb::clang_type_t - GetClangType () = 0; - virtual lldb::ValueType GetValueType() const = 0; @@ -1084,6 +1084,8 @@ protected: std::string m_object_desc_str; // Cached result of the "object printer". This differs from the summary // in that the summary is consed up by us, the object_desc_string is builtin. + ClangASTType m_override_type;// If the type of the value object should be overridden, the type to impose. + ValueObjectManager *m_manager; // This object is managed by the root object (any ValueObject that gets created // without a parent.) The manager gets passed through all the generations of // dependent objects, and will keep the whole cluster of objects alive as long @@ -1119,7 +1121,8 @@ protected: m_is_bitfield_for_scalar:1, m_is_expression_path_child:1, m_is_child_at_offset:1, - m_is_getting_summary:1; + m_is_getting_summary:1, + m_did_calculate_complete_objc_class_type:1; friend class ClangExpressionDeclMap; // For GetValue friend class ClangExpressionVariable; // For SetName @@ -1188,11 +1191,24 @@ protected: DataExtractor & GetDataExtractor (); + //------------------------------------------------------------------ + // Sublasses must implement the functions below. + //------------------------------------------------------------------ + + virtual clang::ASTContext * + GetClangASTImpl () = 0; + + virtual lldb::clang_type_t + GetClangTypeImpl () = 0; + private: //------------------------------------------------------------------ // For ValueObject only //------------------------------------------------------------------ + virtual ClangASTType + MaybeCalculateCompleteType (); + lldb::ValueObjectSP GetValueForExpressionPath_Impl(const char* expression_cstr, const char** first_unparsed, diff --git a/lldb/include/lldb/Core/ValueObjectChild.h b/lldb/include/lldb/Core/ValueObjectChild.h index df8012226c3..2e0384edd0b 100644 --- a/lldb/include/lldb/Core/ValueObjectChild.h +++ b/lldb/include/lldb/Core/ValueObjectChild.h @@ -50,18 +50,6 @@ public: return m_bitfield_bit_offset; } - virtual clang::ASTContext * - GetClangAST () - { - return m_clang_ast; - } - - virtual lldb::clang_type_t - GetClangType () - { - return m_clang_type; - } - virtual lldb::ValueType GetValueType() const; @@ -90,6 +78,18 @@ protected: virtual bool UpdateValue (); + virtual clang::ASTContext * + GetClangASTImpl () + { + return m_clang_ast; + } + + virtual lldb::clang_type_t + GetClangTypeImpl () + { + return m_clang_type; + } + clang::ASTContext *m_clang_ast; // The clang AST that the clang type comes from void *m_clang_type; // The type of the child in question within the parent (m_parent_sp) ConstString m_type_name; diff --git a/lldb/include/lldb/Core/ValueObjectConstResult.h b/lldb/include/lldb/Core/ValueObjectConstResult.h index 54c017c1824..d665efbcb75 100644 --- a/lldb/include/lldb/Core/ValueObjectConstResult.h +++ b/lldb/include/lldb/Core/ValueObjectConstResult.h @@ -75,12 +75,6 @@ public: virtual size_t GetByteSize(); - virtual clang::ASTContext * - GetClangAST (); - - virtual lldb::clang_type_t - GetClangType (); - virtual lldb::ValueType GetValueType() const; @@ -141,6 +135,12 @@ public: protected: virtual bool UpdateValue (); + + virtual clang::ASTContext * + GetClangASTImpl (); + + virtual lldb::clang_type_t + GetClangTypeImpl (); // CalculateDynamicValue doesn't change the dynamic value, since this can get // called at any time and you can't reliably fetch the dynamic value at any time. diff --git a/lldb/include/lldb/Core/ValueObjectDynamicValue.h b/lldb/include/lldb/Core/ValueObjectDynamicValue.h index 361599a91fd..a6fdab49bb6 100644 --- a/lldb/include/lldb/Core/ValueObjectDynamicValue.h +++ b/lldb/include/lldb/Core/ValueObjectDynamicValue.h @@ -33,12 +33,6 @@ namespace lldb_private { virtual size_t GetByteSize(); - virtual clang::ASTContext * - GetClangAST (); - - virtual lldb::clang_type_t - GetClangType (); - virtual ConstString GetTypeName(); @@ -85,6 +79,12 @@ namespace lldb_private { virtual bool UpdateValue (); + virtual clang::ASTContext * + GetClangASTImpl (); + + virtual lldb::clang_type_t + GetClangTypeImpl (); + ClangASTType m_cast_type; private: @@ -111,12 +111,6 @@ public: virtual size_t GetByteSize(); - virtual clang::ASTContext * - GetClangAST (); - - virtual lldb::clang_type_t - GetClangType (); - virtual ConstString GetTypeName(); @@ -172,6 +166,12 @@ public: protected: virtual bool UpdateValue (); + + virtual clang::ASTContext * + GetClangASTImpl (); + + virtual lldb::clang_type_t + GetClangTypeImpl (); Address m_address; ///< The variable that this value object is based upon lldb::TypeSP m_type_sp; diff --git a/lldb/include/lldb/Core/ValueObjectMemory.h b/lldb/include/lldb/Core/ValueObjectMemory.h index 83a5eb9c57a..6cc337b99f5 100644 --- a/lldb/include/lldb/Core/ValueObjectMemory.h +++ b/lldb/include/lldb/Core/ValueObjectMemory.h @@ -44,12 +44,6 @@ public: virtual size_t GetByteSize(); - virtual clang::ASTContext * - GetClangAST (); - - virtual lldb::clang_type_t - GetClangType (); - virtual ConstString GetTypeName(); @@ -68,6 +62,12 @@ public: protected: virtual bool UpdateValue (); + + virtual clang::ASTContext * + GetClangASTImpl (); + + virtual lldb::clang_type_t + GetClangTypeImpl (); Address m_address; ///< The variable that this value object is based upon lldb::TypeSP m_type_sp; diff --git a/lldb/include/lldb/Core/ValueObjectRegister.h b/lldb/include/lldb/Core/ValueObjectRegister.h index dda1556512e..dab37846727 100644 --- a/lldb/include/lldb/Core/ValueObjectRegister.h +++ b/lldb/include/lldb/Core/ValueObjectRegister.h @@ -34,12 +34,6 @@ public: virtual size_t GetByteSize(); - virtual clang::ASTContext * - GetClangAST (); - - virtual lldb::clang_type_t - GetClangType (); - virtual lldb::ValueType GetValueType () const { @@ -58,6 +52,12 @@ public: protected: virtual bool UpdateValue (); + + virtual clang::ASTContext * + GetClangASTImpl (); + + virtual lldb::clang_type_t + GetClangTypeImpl (); lldb::RegisterContextSP m_reg_ctx_sp; @@ -81,12 +81,6 @@ public: virtual size_t GetByteSize(); - virtual clang::ASTContext * - GetClangAST (); - - virtual lldb::clang_type_t - GetClangType (); - virtual lldb::ValueType GetValueType () const { @@ -112,6 +106,12 @@ public: protected: virtual bool UpdateValue (); + + virtual clang::ASTContext * + GetClangASTImpl (); + + virtual lldb::clang_type_t + GetClangTypeImpl (); lldb::RegisterContextSP m_reg_ctx_sp; const RegisterSet *m_reg_set; @@ -139,12 +139,6 @@ public: virtual size_t GetByteSize(); - virtual clang::ASTContext * - GetClangAST (); - - virtual lldb::clang_type_t - GetClangType (); - virtual lldb::ValueType GetValueType () const { @@ -166,6 +160,12 @@ public: protected: virtual bool UpdateValue (); + + virtual clang::ASTContext * + GetClangASTImpl (); + + virtual lldb::clang_type_t + GetClangTypeImpl (); lldb::RegisterContextSP m_reg_ctx_sp; RegisterInfo m_reg_info; diff --git a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h index 01eafe62048..1ef6e4db159 100644 --- a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h +++ b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -36,13 +36,7 @@ public: virtual size_t GetByteSize(); - - virtual clang::ASTContext * - GetClangAST (); - - virtual lldb::clang_type_t - GetClangType (); - + virtual ConstString GetTypeName(); @@ -116,6 +110,12 @@ public: protected: virtual bool UpdateValue (); + + virtual clang::ASTContext * + GetClangASTImpl (); + + virtual lldb::clang_type_t + GetClangTypeImpl (); Address m_address; ///< The variable that this value object is based upon lldb::TypeSP m_type_sp; diff --git a/lldb/include/lldb/Core/ValueObjectVariable.h b/lldb/include/lldb/Core/ValueObjectVariable.h index 20c9589ceca..eec952c5e0e 100644 --- a/lldb/include/lldb/Core/ValueObjectVariable.h +++ b/lldb/include/lldb/Core/ValueObjectVariable.h @@ -34,12 +34,6 @@ public: virtual size_t GetByteSize(); - virtual clang::ASTContext * - GetClangAST (); - - virtual lldb::clang_type_t - GetClangType (); - virtual ConstString GetTypeName(); @@ -64,6 +58,12 @@ public: protected: virtual bool UpdateValue (); + + virtual clang::ASTContext * + GetClangASTImpl (); + + virtual lldb::clang_type_t + GetClangTypeImpl (); lldb::VariableSP m_variable_sp; ///< The variable that this value object is based upon diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h index 02d53e46723..105ec3f72f0 100644 --- a/lldb/include/lldb/Symbol/ClangASTContext.h +++ b/lldb/include/lldb/Symbol/ClangASTContext.h @@ -869,6 +869,13 @@ public: static bool IsObjCClassType (lldb::clang_type_t clang_type); + + static bool + IsObjCObjectPointerType (lldb::clang_type_t clang_type, lldb::clang_type_t *target_type); + + static bool + GetObjCClassName (lldb::clang_type_t clang_type, + std::string &class_name); static bool IsCharType (lldb::clang_type_t clang_type); diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h index 92a847f2372..18fea12d539 100644 --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -265,6 +265,18 @@ public: bool IsRealObjCClass(); + + bool + IsCompleteObjCClass() + { + return m_flags.is_complete_objc_class; + } + + void + SetIsCompleteObjCClass(bool is_complete_objc_class) + { + m_flags.is_complete_objc_class = is_complete_objc_class; + } protected: ConstString m_name; @@ -276,7 +288,11 @@ protected: uint32_t m_byte_size; Declaration m_decl; lldb::clang_type_t m_clang_type; - ResolveState m_clang_type_resolve_state; + + struct Flags { + ResolveState clang_type_resolve_state : 2; + bool is_complete_objc_class : 1; + } m_flags; Type * GetEncodingType (); diff --git a/lldb/include/lldb/Target/ObjCLanguageRuntime.h b/lldb/include/lldb/Target/ObjCLanguageRuntime.h index 05cdce6daa9..fe120472d1f 100644 --- a/lldb/include/lldb/Target/ObjCLanguageRuntime.h +++ b/lldb/include/lldb/Target/ObjCLanguageRuntime.h @@ -18,6 +18,7 @@ // Project includes #include "lldb/lldb-private.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/Type.h" #include "lldb/Target/LanguageRuntime.h" namespace lldb_private { @@ -64,6 +65,9 @@ public: void AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_or_type_name); + lldb::TypeSP + LookupInCompleteClassCache (ConstString &name); + virtual ClangUtilityFunction * CreateObjectChecker (const char *) = 0; @@ -246,6 +250,9 @@ protected: typedef std::map<lldb::addr_t,TypeAndOrName> ClassNameMap; typedef ClassNameMap::iterator ClassNameIterator; ClassNameMap m_class_name_cache; + + typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap; + CompleteClassMap m_complete_class_cache; DISALLOW_COPY_AND_ASSIGN (ObjCLanguageRuntime); }; diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 0c75affd1bd..15885eb691f 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -95,7 +95,8 @@ ValueObject::ValueObject (ValueObject &parent) : m_is_bitfield_for_scalar(false), m_is_expression_path_child(false), m_is_child_at_offset(false), - m_is_getting_summary(false) + m_is_getting_summary(false), + m_did_calculate_complete_objc_class_type(false) { m_manager->ManageObject(this); } @@ -141,7 +142,8 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope, m_is_bitfield_for_scalar(false), m_is_expression_path_child(false), m_is_child_at_offset(false), - m_is_getting_summary(false) + m_is_getting_summary(false), + m_did_calculate_complete_objc_class_type(false) { m_manager = new ValueObjectManager(); m_manager->ManageObject (this); @@ -271,6 +273,103 @@ ValueObject::SetNeedsUpdate () m_value_str.clear(); } +ClangASTType +ValueObject::MaybeCalculateCompleteType () +{ + ClangASTType ret(GetClangASTImpl(), GetClangTypeImpl()); + + if (m_did_calculate_complete_objc_class_type) + { + if (m_override_type.IsValid()) + return m_override_type; + else + return ret; + } + + clang_type_t ast_type(GetClangTypeImpl()); + clang_type_t class_type; + bool is_pointer_type; + + if (ClangASTContext::IsObjCObjectPointerType(ast_type, &class_type)) + { + is_pointer_type = true; + } + else if (ClangASTContext::IsObjCClassType(ast_type)) + { + is_pointer_type = false; + class_type = ast_type; + } + else + { + return ret; + } + + m_did_calculate_complete_objc_class_type = true; + + if (!class_type) + return ret; + + std::string class_name; + + if (!ClangASTContext::GetObjCClassName(class_type, class_name)) + return ret; + + ProcessSP process_sp(GetUpdatePoint().GetExecutionContextRef().GetProcessSP()); + + if (!process_sp) + return ret; + + ObjCLanguageRuntime *objc_language_runtime(process_sp->GetObjCLanguageRuntime()); + + if (!objc_language_runtime) + return ret; + + ConstString class_name_cs(class_name.c_str()); + + TypeSP complete_objc_class_type_sp = objc_language_runtime->LookupInCompleteClassCache(class_name_cs); + + if (!complete_objc_class_type_sp) + return ret; + + ClangASTType complete_class(complete_objc_class_type_sp->GetClangAST(), + complete_objc_class_type_sp->GetClangFullType()); + + if (!ClangASTContext::GetCompleteType(complete_class.GetASTContext(), + complete_class.GetOpaqueQualType())) + return ret; + + if (is_pointer_type) + { + clang_type_t pointer_type = ClangASTContext::CreatePointerType(complete_class.GetASTContext(), + complete_class.GetOpaqueQualType()); + + m_override_type = ClangASTType(complete_class.GetASTContext(), + pointer_type); + } + else + { + m_override_type = complete_class; + } + + return m_override_type; +} + +clang::ASTContext * +ValueObject::GetClangAST () +{ + ClangASTType type = MaybeCalculateCompleteType(); + + return type.GetASTContext(); +} + +lldb::clang_type_t +ValueObject::GetClangType () +{ + ClangASTType type = MaybeCalculateCompleteType(); + + return type.GetOpaqueQualType(); +} + DataExtractor & ValueObject::GetDataExtractor () { diff --git a/lldb/source/Core/ValueObjectChild.cpp b/lldb/source/Core/ValueObjectChild.cpp index eb247904742..91522ba4b72 100644 --- a/lldb/source/Core/ValueObjectChild.cpp +++ b/lldb/source/Core/ValueObjectChild.cpp @@ -65,7 +65,7 @@ ValueObjectChild::GetValueType() const uint32_t ValueObjectChild::CalculateNumChildren() { - return ClangASTContext::GetNumChildren (GetClangAST (), m_clang_type, true); + return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true); } ConstString @@ -101,7 +101,7 @@ ValueObjectChild::UpdateValue () { if (parent->UpdateValueIfNeeded(false)) { - m_value.SetContext(Value::eContextTypeClangType, m_clang_type); + m_value.SetContext(Value::eContextTypeClangType, GetClangType()); // Copy the parent scalar value and the scalar value type m_value.GetScalar() = parent->GetValue().GetScalar(); diff --git a/lldb/source/Core/ValueObjectConstResult.cpp b/lldb/source/Core/ValueObjectConstResult.cpp index ee82e24980f..dfa4cfa981a 100644 --- a/lldb/source/Core/ValueObjectConstResult.cpp +++ b/lldb/source/Core/ValueObjectConstResult.cpp @@ -275,7 +275,7 @@ ValueObjectConstResult::~ValueObjectConstResult() } lldb::clang_type_t -ValueObjectConstResult::GetClangType() +ValueObjectConstResult::GetClangTypeImpl() { return m_value.GetClangType(); } @@ -307,7 +307,7 @@ ValueObjectConstResult::CalculateNumChildren() } clang::ASTContext * -ValueObjectConstResult::GetClangAST () +ValueObjectConstResult::GetClangASTImpl () { return m_clang_ast; } diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp index e608ce9bb70..b336a7fa274 100644 --- a/lldb/source/Core/ValueObjectDynamicValue.cpp +++ b/lldb/source/Core/ValueObjectDynamicValue.cpp @@ -61,7 +61,7 @@ ValueObjectCast::~ValueObjectCast() } lldb::clang_type_t -ValueObjectCast::GetClangType () +ValueObjectCast::GetClangTypeImpl () { return m_cast_type.GetOpaqueQualType(); } @@ -79,7 +79,7 @@ ValueObjectCast::CalculateNumChildren() } clang::ASTContext * -ValueObjectCast::GetClangAST () +ValueObjectCast::GetClangASTImpl () { return m_cast_type.GetASTContext(); } @@ -159,7 +159,7 @@ ValueObjectDynamicValue::~ValueObjectDynamicValue() } lldb::clang_type_t -ValueObjectDynamicValue::GetClangType () +ValueObjectDynamicValue::GetClangTypeImpl () { if (m_type_sp) return m_value.GetClangType(); @@ -188,7 +188,7 @@ ValueObjectDynamicValue::CalculateNumChildren() } clang::ASTContext * -ValueObjectDynamicValue::GetClangAST () +ValueObjectDynamicValue::GetClangASTImpl () { const bool success = UpdateValueIfNeeded(false); if (success && m_type_sp) diff --git a/lldb/source/Core/ValueObjectMemory.cpp b/lldb/source/Core/ValueObjectMemory.cpp index 9f26a460864..970cd267fdd 100644 --- a/lldb/source/Core/ValueObjectMemory.cpp +++ b/lldb/source/Core/ValueObjectMemory.cpp @@ -131,7 +131,7 @@ ValueObjectMemory::~ValueObjectMemory() } lldb::clang_type_t -ValueObjectMemory::GetClangType () +ValueObjectMemory::GetClangTypeImpl () { if (m_type_sp) return m_type_sp->GetClangForwardType(); @@ -158,7 +158,7 @@ ValueObjectMemory::CalculateNumChildren() } clang::ASTContext * -ValueObjectMemory::GetClangAST () +ValueObjectMemory::GetClangASTImpl () { if (m_type_sp) return m_type_sp->GetClangAST(); diff --git a/lldb/source/Core/ValueObjectRegister.cpp b/lldb/source/Core/ValueObjectRegister.cpp index d96a5af0b0a..1b1b779f795 100644 --- a/lldb/source/Core/ValueObjectRegister.cpp +++ b/lldb/source/Core/ValueObjectRegister.cpp @@ -43,7 +43,7 @@ ValueObjectRegisterContext::~ValueObjectRegisterContext() } lldb::clang_type_t -ValueObjectRegisterContext::GetClangType () +ValueObjectRegisterContext::GetClangTypeImpl () { return NULL; } @@ -62,7 +62,7 @@ ValueObjectRegisterContext::CalculateNumChildren() } clang::ASTContext * -ValueObjectRegisterContext::GetClangAST () +ValueObjectRegisterContext::GetClangASTImpl () { return NULL; } @@ -140,7 +140,7 @@ ValueObjectRegisterSet::~ValueObjectRegisterSet() } lldb::clang_type_t -ValueObjectRegisterSet::GetClangType () +ValueObjectRegisterSet::GetClangTypeImpl () { return NULL; } @@ -161,7 +161,7 @@ ValueObjectRegisterSet::CalculateNumChildren() } clang::ASTContext * -ValueObjectRegisterSet::GetClangAST () +ValueObjectRegisterSet::GetClangASTImpl () { return NULL; } @@ -303,7 +303,7 @@ ValueObjectRegister::~ValueObjectRegister() } lldb::clang_type_t -ValueObjectRegister::GetClangType () +ValueObjectRegister::GetClangTypeImpl () { if (m_clang_type == NULL) { @@ -337,7 +337,7 @@ ValueObjectRegister::CalculateNumChildren() } clang::ASTContext * -ValueObjectRegister::GetClangAST () +ValueObjectRegister::GetClangASTImpl () { ExecutionContext exe_ctx (GetExecutionContextRef()); Target *target = exe_ctx.GetTargetPtr(); diff --git a/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/lldb/source/Core/ValueObjectSyntheticFilter.cpp index 31d3fa18564..1e2cea34f8d 100644 --- a/lldb/source/Core/ValueObjectSyntheticFilter.cpp +++ b/lldb/source/Core/ValueObjectSyntheticFilter.cpp @@ -54,7 +54,7 @@ ValueObjectSynthetic::~ValueObjectSynthetic() } lldb::clang_type_t -ValueObjectSynthetic::GetClangType () +ValueObjectSynthetic::GetClangTypeImpl () { if (m_type_sp) return m_value.GetClangType(); @@ -79,7 +79,7 @@ ValueObjectSynthetic::CalculateNumChildren() } clang::ASTContext * -ValueObjectSynthetic::GetClangAST () +ValueObjectSynthetic::GetClangASTImpl () { const bool success = UpdateValueIfNeeded(false); if (success && m_type_sp) diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index 24f189d9f95..653b3cb58e8 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -53,7 +53,7 @@ ValueObjectVariable::~ValueObjectVariable() } lldb::clang_type_t -ValueObjectVariable::GetClangType () +ValueObjectVariable::GetClangTypeImpl () { Type *var_type = m_variable_sp->GetType(); if (var_type) @@ -73,15 +73,19 @@ ValueObjectVariable::GetTypeName() uint32_t ValueObjectVariable::CalculateNumChildren() -{ - Type *var_type = m_variable_sp->GetType(); - if (var_type) - return var_type->GetNumChildren(true); - return 0; +{ + ClangASTType type(GetClangAST(), + GetClangType()); + + if (!type.IsValid()) + return 0; + + const bool omit_empty_base_classes = true; + return ClangASTContext::GetNumChildren(type.GetASTContext(), type.GetOpaqueQualType(), omit_empty_base_classes); } clang::ASTContext * -ValueObjectVariable::GetClangAST () +ValueObjectVariable::GetClangASTImpl () { Type *var_type = m_variable_sp->GetType(); if (var_type) @@ -92,10 +96,13 @@ ValueObjectVariable::GetClangAST () size_t ValueObjectVariable::GetByteSize() { - Type *type = m_variable_sp->GetType(); - if (type) - return type->GetByteSize(); - return 0; + ClangASTType type(GetClangAST(), + GetClangType()); + + if (!type.IsValid()) + return 0; + + return (ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType()) + 7) / 8; } lldb::ValueType diff --git a/lldb/source/Expression/ClangASTSource.cpp b/lldb/source/Expression/ClangASTSource.cpp index 7cdc3f62222..3376bd1c5b1 100644 --- a/lldb/source/Expression/ClangASTSource.cpp +++ b/lldb/source/Expression/ClangASTSource.cpp @@ -847,36 +847,29 @@ DeclFromUser<D>::Import(ClangASTImporter *importer, ASTContext &dest_ctx) return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl)); } -void -ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) +static bool +FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, + NameSearchContext &context, + clang::ASTContext &ast_context, + ClangASTImporter *ast_importer, + DeclFromUser<const ObjCInterfaceDecl> &origin_iface_decl) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; - - DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context)); - DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer)); - if (origin_iface_decl.IsInvalid()) - return; + return false; std::string name_str = context.m_decl_name.getAsString(); StringRef name(name_str.c_str()); IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name)); - if (log) - log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'", - current_id, - m_ast_context, - parser_iface_decl->getNameAsString().c_str(), - name_str.c_str()); - DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier)); + bool found = false; + if (origin_property_decl.IsValid()) { - DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(m_ast_importer, *m_ast_context)); + DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(ast_importer, ast_context)); if (parser_property_decl.IsValid()) { if (log) @@ -886,6 +879,7 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) } context.AddNamedDecl(parser_property_decl.decl); + found = true; } } @@ -893,7 +887,7 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) if (origin_ivar_decl.IsValid()) { - DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(m_ast_importer, *m_ast_context)); + DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(ast_importer, ast_context)); if (parser_ivar_decl.IsValid()) { if (log) @@ -903,8 +897,94 @@ ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) } context.AddNamedDecl(parser_ivar_decl.decl); + found = true; } } + + return found; +} + +void +ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) +{ + lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context)); + DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer)); + + ConstString class_name(parser_iface_decl->getNameAsString().c_str()); + + if (log) + log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'", + current_id, + m_ast_context, + parser_iface_decl->getNameAsString().c_str(), + context.m_decl_name.getAsString().c_str()); + + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer, + origin_iface_decl)) + return; + + if (log) + log->Printf("CAS::FOPD[%d] couldn't find the property on origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching elsewhere...", + current_id, + origin_iface_decl.decl, + &origin_iface_decl->getASTContext()); + + SymbolContext null_sc; + TypeList type_list; + + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + return; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + if (!language_runtime) + return; + + lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name)); + + if (!complete_type_sp) + return; + + TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetClangFullType(), complete_type_sp->GetClangAST()); + lldb::clang_type_t complete_opaque_type = complete_type.GetOpaqueQualType(); + + if (!complete_opaque_type) + return; + + const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr(); + const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type); + + if (!complete_interface_type) + return; + + DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_type->getDecl()); + + if (complete_iface_decl.decl == origin_iface_decl.decl) + return; // already checked this one + + if (log) + log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + complete_iface_decl.decl, + &complete_iface_decl->getASTContext()); + + + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer, + complete_iface_decl)) + return; } typedef llvm::DenseMap <const FieldDecl *, uint64_t> FieldOffsetMap; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 380da92acea..56fc593c1b8 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -4962,6 +4962,8 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, &decl, clang_type, Type::eResolveStateForward)); + + type_sp->SetIsCompleteObjCClass(is_complete_objc_class); // Add our type to the unique type map so we don't diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 9bb893ced20..7c744fbde05 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -5831,6 +5831,49 @@ ClangASTContext::IsObjCClassType (clang_type_t clang_type) return false; } +bool +ClangASTContext::IsObjCObjectPointerType (lldb::clang_type_t clang_type, clang_type_t *class_type) +{ + if (clang_type) + { + QualType qual_type (QualType::getFromOpaquePtr(clang_type)); + if (qual_type->isObjCObjectPointerType()) + { + if (class_type) + { + *class_type = NULL; + + if (!qual_type->isObjCClassType() && + !qual_type->isObjCIdType()) + { + const ObjCObjectPointerType *obj_pointer_type = dyn_cast<ObjCObjectPointerType>(qual_type); + *class_type = QualType(obj_pointer_type->getInterfaceType(), 0).getAsOpaquePtr(); + } + } + return true; + } + } + return false; +} + +bool +ClangASTContext::GetObjCClassName (lldb::clang_type_t clang_type, + std::string &class_name) +{ + if (!clang_type) + return false; + + const ObjCObjectType *object_type = dyn_cast<ObjCObjectType>(QualType::getFromOpaquePtr(clang_type)); + if (!object_type) + return false; + + const ObjCInterfaceDecl *interface = object_type->getInterface(); + if (!interface) + return false; + + class_name = interface->getNameAsString(); + return true; +} bool ClangASTContext::IsCharType (clang_type_t clang_type) diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 0844a9ecc6c..a50c98d4727 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -20,6 +20,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContextScope.h" #include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Type.h" #include "lldb/Symbol/TypeList.h" @@ -61,9 +62,10 @@ Type::Type m_encoding_uid_type (encoding_uid_type), m_byte_size (byte_size), m_decl (decl), - m_clang_type (clang_type), - m_clang_type_resolve_state (clang_type ? clang_type_resolve_state : eResolveStateUnresolved) + m_clang_type (clang_type) { + m_flags.clang_type_resolve_state = (clang_type ? clang_type_resolve_state : eResolveStateUnresolved); + m_flags.is_complete_objc_class = false; } Type::Type () : @@ -76,9 +78,10 @@ Type::Type () : m_encoding_uid_type (eEncodingInvalid), m_byte_size (0), m_decl (), - m_clang_type (NULL), - m_clang_type_resolve_state (eResolveStateUnresolved) + m_clang_type (NULL) { + m_flags.clang_type_resolve_state = eResolveStateUnresolved; + m_flags.is_complete_objc_class = false; } @@ -93,7 +96,7 @@ Type::Type (const Type &rhs) : m_byte_size (rhs.m_byte_size), m_decl (rhs.m_decl), m_clang_type (rhs.m_clang_type), - m_clang_type_resolve_state (rhs.m_clang_type_resolve_state) + m_flags (rhs.m_flags) { } @@ -458,7 +461,7 @@ Type::ResolveClangType (ResolveState clang_type_resolve_state) if (encoding_type->ResolveClangType(clang_type_resolve_state)) { m_clang_type = encoding_type->m_clang_type; - m_clang_type_resolve_state = encoding_type->m_clang_type_resolve_state; + m_flags.clang_type_resolve_state = encoding_type->m_flags.clang_type_resolve_state; } break; @@ -544,9 +547,9 @@ Type::ResolveClangType (ResolveState clang_type_resolve_state) } // Check if we have a forward reference to a class/struct/union/enum? - if (m_clang_type && m_clang_type_resolve_state < clang_type_resolve_state) + if (m_clang_type && m_flags.clang_type_resolve_state < clang_type_resolve_state) { - m_clang_type_resolve_state = eResolveStateFull; + m_flags.clang_type_resolve_state = eResolveStateFull; if (!ClangASTType::IsDefined (m_clang_type)) { // We have a forward declaration, we need to resolve it to a complete diff --git a/lldb/source/Target/ObjCLanguageRuntime.cpp b/lldb/source/Target/ObjCLanguageRuntime.cpp index 00d3aa4f47f..0076ff04ca7 100644 --- a/lldb/source/Target/ObjCLanguageRuntime.cpp +++ b/lldb/source/Target/ObjCLanguageRuntime.cpp @@ -14,6 +14,7 @@ #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Type.h" #include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" using namespace lldb; using namespace lldb_private; @@ -94,6 +95,84 @@ ObjCLanguageRuntime::LookupInClassNameCache (lldb::addr_t class_addr) return TypeAndOrName (); } +lldb::TypeSP +ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name) +{ + CompleteClassMap::iterator complete_class_iter = m_complete_class_cache.find(name); + + if (complete_class_iter != m_complete_class_cache.end()) + { + TypeSP ret(complete_class_iter->second); + + if (!ret) + m_complete_class_cache.erase(name); + else + return TypeSP(complete_class_iter->second); + } + + ModuleList &modules = m_process->GetTarget().GetImages(); + + SymbolContextList sc_list; + + modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list); + + if (sc_list.GetSize() == 0) + return TypeSP(); + + SymbolContext sc; + + sc_list.GetContextAtIndex(0, sc); + + ModuleSP module_sp(sc.module_sp); + + if (!module_sp) + return TypeSP(); + + const SymbolContext null_sc; + const ClangNamespaceDecl *null_namespace_decl = NULL; + const bool append = false; + const uint32_t max_matches = UINT32_MAX; + TypeList types; + + module_sp->FindTypes(null_sc, + name, + null_namespace_decl, + append, + max_matches, + types); + + if (types.GetSize() == 1) + { + TypeSP candidate_type = types.GetTypeAtIndex(0); + + if (ClangASTContext::IsObjCClassType(candidate_type->GetClangForwardType())) + { + m_complete_class_cache[name] = TypeWP(candidate_type); + return candidate_type; + } + else + { + return TypeSP(); + } + } + + for (uint32_t ti = 0, te = types.GetSize(); + ti < te; + ++ti) + { + TypeSP candidate_type = types.GetTypeAtIndex(ti); + + if (candidate_type->IsCompleteObjCClass() && + ClangASTContext::IsObjCClassType(candidate_type->GetClangForwardType())) + { + m_complete_class_cache[name] = TypeWP(candidate_type); + return candidate_type; + } + } + + return TypeSP(); +} + size_t ObjCLanguageRuntime::GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name) { diff --git a/lldb/test/lang/objc/hidden-ivars/InternalDefiner.h b/lldb/test/lang/objc/hidden-ivars/InternalDefiner.h new file mode 100644 index 00000000000..b9b54707ae5 --- /dev/null +++ b/lldb/test/lang/objc/hidden-ivars/InternalDefiner.h @@ -0,0 +1,10 @@ +#import <Foundation/Foundation.h> + +@interface InternalDefiner : NSObject { +@public + int foo; +} + +-(int)setBarTo:(int)newBar; + +@end diff --git a/lldb/test/lang/objc/hidden-ivars/InternalDefiner.m b/lldb/test/lang/objc/hidden-ivars/InternalDefiner.m new file mode 100644 index 00000000000..97536b163e7 --- /dev/null +++ b/lldb/test/lang/objc/hidden-ivars/InternalDefiner.m @@ -0,0 +1,18 @@ +#import "InternalDefiner.h" + +@interface InternalDefiner () { + int bar; +} + +@end + +@implementation InternalDefiner + +-(int)setBarTo:(int)newBar +{ + int oldBar = bar; + bar = newBar; + return oldBar; +} + +@end diff --git a/lldb/test/lang/objc/hidden-ivars/Makefile b/lldb/test/lang/objc/hidden-ivars/Makefile new file mode 100644 index 00000000000..e99c30c117d --- /dev/null +++ b/lldb/test/lang/objc/hidden-ivars/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +DYLIB_NAME := libInternalDefiner +DYLIB_OBJC_SOURCES := InternalDefiner.m +OBJC_SOURCES := main.m + +LDFLAGS = -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/lldb/test/lang/objc/hidden-ivars/TestHiddenIvars.py b/lldb/test/lang/objc/hidden-ivars/TestHiddenIvars.py new file mode 100644 index 00000000000..f0bb94b70f3 --- /dev/null +++ b/lldb/test/lang/objc/hidden-ivars/TestHiddenIvars.py @@ -0,0 +1,77 @@ +"""Test that hidden ivars in a shared library are visible from the main executable.""" + +import os, time +import unittest2 +import lldb +from lldbtest import * + +class HiddenIvarsTestCase(TestBase): + + mydir = os.path.join("lang", "objc", "hidden-ivars") + + def test_expr_with_dsym(self): + self.buildDsym() + self.expr() + + def test_expr_with_dwarf(self): + self.buildDwarf() + self.expr() + + def test_frame_variable_with_dsym(self): + self.buildDsym() + self.frame_var() + + def test_frame_variable_with_dwarf(self): + self.buildDwarf() + self.frame_var() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.m', '// Set breakpoint 0 here.') + + def common_setup(self): + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break inside the foo function which takes a bar_ptr argument. + self.expect("breakpoint set -f main.m -l %d" % self.line, BREAKPOINT_CREATED, + startstr = "Breakpoint created") + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs = [' resolved, hit count = 1']) + + def expr(self): + self.common_setup() + + # This should display correctly. + self.expect("expression (i->bar)", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["= 3"]) + + self.expect("expression (*i)", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["foo = 0", "bar = 3"]) + + def frame_var(self): + self.common_setup() + + # This should display correctly. + self.expect("frame variable i->bar", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["= 3"]) + + self.expect("frame variable *i", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["foo = 0", "bar = 3"]) + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/lang/objc/hidden-ivars/main.m b/lldb/test/lang/objc/hidden-ivars/main.m new file mode 100644 index 00000000000..0b219596aa5 --- /dev/null +++ b/lldb/test/lang/objc/hidden-ivars/main.m @@ -0,0 +1,18 @@ +#import <Foundation/Foundation.h> +#import "InternalDefiner.h" + +int main(int argc, const char * argv[]) +{ + + @autoreleasepool { + + InternalDefiner *i = [InternalDefiner alloc]; + + [i setBarTo:3]; + + printf("ivar value = %d", i->foo); // Set breakpoint 0 here. + + } + return 0; +} + diff --git a/lldb/test/make/Makefile.rules b/lldb/test/make/Makefile.rules index 238acb77e57..53beb1e88e7 100644 --- a/lldb/test/make/Makefile.rules +++ b/lldb/test/make/Makefile.rules @@ -95,6 +95,10 @@ ifneq "$(strip $(DYLIB_C_SOURCES))" "" DYLIB_OBJECTS +=$(strip $(DYLIB_C_SOURCES:.c=.o)) endif +ifneq "$(strip $(DYLIB_OBJC_SOURCES))" "" + DYLIB_OBJECTS +=$(strip $(DYLIB_OBJC_SOURCES:.m=.o)) +endif + ifneq "$(strip $(DYLIB_CXX_SOURCES))" "" DYLIB_OBJECTS +=$(strip $(DYLIB_CXX_SOURCES:.cpp=.o)) CXX = $(call cxx_compiler,$(CC)) |