[Lldb-commits] [lldb] r172880 - in /lldb/trunk: source/Expression/ClangExpressionDeclMap.cpp source/Expression/ClangUserExpression.cpp test/lang/objc/blocks/TestObjCIvarsInBlocks.py test/lang/objc/blocks/ivars-in-blocks.h test/lang/objc/blocks/ivars-in-blocks.m
Sean Callanan
scallanan at apple.com
Fri Jan 18 17:49:02 PST 2013
Author: spyffe
Date: Fri Jan 18 19:49:02 2013
New Revision: 172880
URL: http://llvm.org/viewvc/llvm-project?rev=172880&view=rev
Log:
Extended LLDB to handle blocks capturing 'self'
in an Objective-C class method. Before, errors
of the form
error: cannot find interface declaration for '$__lldb_objc_class'
would appear when running any expression when
the current frame is a block that captures 'self'
from an Objective-C class method.
<rdar://problem/12905561>
Modified:
lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
lldb/trunk/source/Expression/ClangUserExpression.cpp
lldb/trunk/test/lang/objc/blocks/TestObjCIvarsInBlocks.py
lldb/trunk/test/lang/objc/blocks/ivars-in-blocks.h
lldb/trunk/test/lang/objc/blocks/ivars-in-blocks.m
Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=172880&r1=172879&r2=172880&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Fri Jan 18 19:49:02 2013
@@ -2758,7 +2758,6 @@
if (method_decl)
{
-
ObjCInterfaceDecl* self_interface = method_decl->getClassInterface();
if (!self_interface)
@@ -2822,10 +2821,15 @@
return;
QualType self_qual_type = QualType::getFromOpaquePtr(self_type->GetClangFullType());
- const ObjCObjectPointerType *class_pointer_type = self_qual_type->getAs<ObjCObjectPointerType>();
- if (class_pointer_type)
+ if (self_qual_type->isObjCClassType())
+ {
+ return;
+ }
+ else if (self_qual_type->isObjCObjectPointerType())
{
+ const ObjCObjectPointerType *class_pointer_type = self_qual_type->getAs<ObjCObjectPointerType>();
+
QualType class_type = class_pointer_type->getPointeeType();
if (log)
@@ -2835,10 +2839,10 @@
}
TypeFromUser class_user_type (class_type.getAsOpaquePtr(),
- self_type->GetClangAST());
+ self_type->GetClangAST());
+
AddOneType(context, class_user_type, current_id, false);
-
TypeFromUser self_user_type(self_type->GetClangFullType(),
self_type->GetClangAST());
Modified: lldb/trunk/source/Expression/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?rev=172880&r1=172879&r2=172880&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangUserExpression.cpp Fri Jan 18 19:49:02 2013
@@ -234,13 +234,94 @@
lldb::LanguageType language = metadata->GetObjectPtrLanguage();
if (language == lldb::eLanguageTypeC_plus_plus)
{
+ if (m_enforce_valid_object)
+ {
+ lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
+
+ const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context";
+
+ if (!variable_list_sp)
+ {
+ err.SetErrorString(thisErrorString);
+ return;
+ }
+
+ lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
+
+ if (!this_var_sp ||
+ !this_var_sp->IsInScope(frame) ||
+ !this_var_sp->LocationIsValidForFrame (frame))
+ {
+ err.SetErrorString(thisErrorString);
+ return;
+ }
+ }
+
m_cplusplus = true;
m_needs_object_ptr = true;
}
else if (language == lldb::eLanguageTypeObjC)
{
- m_objectivec = true;
- m_needs_object_ptr = true;
+ if (m_enforce_valid_object)
+ {
+ lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
+
+ const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context";
+
+ if (!variable_list_sp)
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
+
+ if (!self_variable_sp ||
+ !self_variable_sp->IsInScope(frame) ||
+ !self_variable_sp->LocationIsValidForFrame (frame))
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ Type *self_type = self_variable_sp->GetType();
+
+ if (!self_type)
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ lldb::clang_type_t self_opaque_type = self_type->GetClangForwardType();
+
+ if (!self_opaque_type)
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ clang::QualType self_qual_type = clang::QualType::getFromOpaquePtr(self_opaque_type);
+
+ if (self_qual_type->isObjCClassType())
+ {
+ return;
+ }
+ else if (self_qual_type->isObjCObjectPointerType())
+ {
+ m_objectivec = true;
+ m_needs_object_ptr = true;
+ }
+ else
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+ }
+ else
+ {
+ m_objectivec = true;
+ m_needs_object_ptr = true;
+ }
}
}
}
Modified: lldb/trunk/test/lang/objc/blocks/TestObjCIvarsInBlocks.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/blocks/TestObjCIvarsInBlocks.py?rev=172880&r1=172879&r2=172880&view=diff
==============================================================================
--- lldb/trunk/test/lang/objc/blocks/TestObjCIvarsInBlocks.py (original)
+++ lldb/trunk/test/lang/objc/blocks/TestObjCIvarsInBlocks.py Fri Jan 18 19:49:02 2013
@@ -48,6 +48,9 @@
breakpoint = target.BreakpointCreateBySourceRegex ('// Break here inside the block.', self.class_source_file_spec)
self.assertTrue(breakpoint, VALID_BREAKPOINT)
+ breakpoint_two = target.BreakpointCreateBySourceRegex ('// Break here inside the class method block.', self.class_source_file_spec)
+ self.assertTrue(breakpoint, VALID_BREAKPOINT)
+
process = target.LaunchSimple (None, None, os.getcwd())
self.assertTrue (process, "Created a process.")
self.assertTrue (process.GetState() == lldb.eStateStopped, "Stopped it too.")
@@ -94,6 +97,21 @@
self.assertTrue (error.Success(), "Got value from indirect access using the expression parser")
self.assertTrue (direct_value == indirect_value, "Direct ivar access and indirect through expression parser produce same value.")
+
+ process.Continue()
+ self.assertTrue (process.GetState() == lldb.eStateStopped, "Stopped at the second breakpoint.")
+
+ thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint_two)
+ self.assertTrue (len(thread_list) == 1)
+ thread = thread_list[0]
+
+ frame = thread.GetFrameAtIndex(0)
+ self.assertTrue (frame, "frame 0 is valid")
+
+ expr = frame.EvaluateExpression("(ret)")
+ self.assertTrue (expr, "Successfully got a local variable in a block in a class method.")
+
+ self.assertTrue (expr.GetValueAsSigned (error) == 5, "The local variable in the block was what we expected.")
if __name__ == '__main__':
import atexit
Modified: lldb/trunk/test/lang/objc/blocks/ivars-in-blocks.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/blocks/ivars-in-blocks.h?rev=172880&r1=172879&r2=172880&view=diff
==============================================================================
--- lldb/trunk/test/lang/objc/blocks/ivars-in-blocks.h (original)
+++ lldb/trunk/test/lang/objc/blocks/ivars-in-blocks.h Fri Jan 18 19:49:02 2013
@@ -5,6 +5,7 @@
@public
int blocky_ivar;
}
++ (void) classMethod;
- (IAmBlocky *) init;
- (int) callABlock: (int) block_value;
@end
Modified: lldb/trunk/test/lang/objc/blocks/ivars-in-blocks.m
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/blocks/ivars-in-blocks.m?rev=172880&r1=172879&r2=172880&view=diff
==============================================================================
--- lldb/trunk/test/lang/objc/blocks/ivars-in-blocks.m (original)
+++ lldb/trunk/test/lang/objc/blocks/ivars-in-blocks.m Fri Jan 18 19:49:02 2013
@@ -11,7 +11,22 @@
@end
@implementation IAmBlocky
+
++ (int) addend
+{
+ return 3;
+}
++ (void) classMethod
+{
+ int (^my_block)(int) = ^(int foo)
+ {
+ int ret = foo + [self addend];
+ return ret; // Break here inside the class method block.
+ };
+ printf("%d\n", my_block(2));
+}
+
- (void) makeBlockPtr;
{
_block_ptr = ^(int inval)
@@ -34,7 +49,9 @@
{
if (_block_ptr == NULL)
[self makeBlockPtr];
- return _block_ptr (block_value);
+ int ret = _block_ptr (block_value);
+ [IAmBlocky classMethod];
+ return ret;
}
@end
More information about the lldb-commits
mailing list