summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Core/ValueObject.h30
-rw-r--r--lldb/include/lldb/Core/ValueObjectChild.h24
-rw-r--r--lldb/include/lldb/Core/ValueObjectConstResult.h12
-rw-r--r--lldb/include/lldb/Core/ValueObjectDynamicValue.h24
-rw-r--r--lldb/include/lldb/Core/ValueObjectMemory.h12
-rw-r--r--lldb/include/lldb/Core/ValueObjectRegister.h36
-rw-r--r--lldb/include/lldb/Core/ValueObjectSyntheticFilter.h14
-rw-r--r--lldb/include/lldb/Core/ValueObjectVariable.h12
-rw-r--r--lldb/include/lldb/Symbol/ClangASTContext.h7
-rw-r--r--lldb/include/lldb/Symbol/Type.h18
-rw-r--r--lldb/include/lldb/Target/ObjCLanguageRuntime.h7
-rw-r--r--lldb/source/Core/ValueObject.cpp103
-rw-r--r--lldb/source/Core/ValueObjectChild.cpp4
-rw-r--r--lldb/source/Core/ValueObjectConstResult.cpp4
-rw-r--r--lldb/source/Core/ValueObjectDynamicValue.cpp8
-rw-r--r--lldb/source/Core/ValueObjectMemory.cpp4
-rw-r--r--lldb/source/Core/ValueObjectRegister.cpp12
-rw-r--r--lldb/source/Core/ValueObjectSyntheticFilter.cpp4
-rw-r--r--lldb/source/Core/ValueObjectVariable.cpp29
-rw-r--r--lldb/source/Expression/ClangASTSource.cpp116
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp2
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp43
-rw-r--r--lldb/source/Symbol/Type.cpp19
-rw-r--r--lldb/source/Target/ObjCLanguageRuntime.cpp79
-rw-r--r--lldb/test/lang/objc/hidden-ivars/InternalDefiner.h10
-rw-r--r--lldb/test/lang/objc/hidden-ivars/InternalDefiner.m18
-rw-r--r--lldb/test/lang/objc/hidden-ivars/Makefile9
-rw-r--r--lldb/test/lang/objc/hidden-ivars/TestHiddenIvars.py77
-rw-r--r--lldb/test/lang/objc/hidden-ivars/main.m18
-rw-r--r--lldb/test/make/Makefile.rules4
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))
OpenPOWER on IntegriCloud