diff options
| author | Sean Callanan <scallanan@apple.com> | 2012-02-22 23:57:45 +0000 |
|---|---|---|
| committer | Sean Callanan <scallanan@apple.com> | 2012-02-22 23:57:45 +0000 |
| commit | 7277284f87dd195294355416d29ff3e6715d037a (patch) | |
| tree | 0869c062a22cad4c17e2e98015b8beaa183bd598 | |
| parent | 9646a472da57c03b44dd4286de571426117395fa (diff) | |
| download | bcm5719-llvm-7277284f87dd195294355416d29ff3e6715d037a.tar.gz bcm5719-llvm-7277284f87dd195294355416d29ff3e6715d037a.zip | |
Added support for looking up the complete type for
Objective-C classes. This allows LLDB to find
ivars declared in class extensions in modules other
than where the debugger is currently stopped (we
already supported this when the debugger was
stopped in the same module as the definition).
This involved the following main changes:
- The ObjCLanguageRuntime now knows how to hunt
for the authoritative version of an Objective-C
type. It looks for the symbol indicating a
definition, and then gets the type from the
module containing that symbol.
- ValueObjects now report their type with a
potential override, and the override is set if
the type of the ValueObject is an Objective-C
class or pointer type that is defined somewhere
other than the original reported type. This
means that "frame variable" will always use the
complete type if one is available.
- The ClangASTSource now looks for the complete
type when looking for ivars. This means that
"expr" will always use the complete type if one
is available.
- I added a testcase that verifies that both
"frame variable" and "expr" work.
llvm-svn: 151214
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)) |

