diff options
author | Aleksandr Urakov <aleksandr.urakov@jetbrains.com> | 2019-02-05 09:14:36 +0000 |
---|---|---|
committer | Aleksandr Urakov <aleksandr.urakov@jetbrains.com> | 2019-02-05 09:14:36 +0000 |
commit | 40624a085c03fb6d41834885d41f7158ab72950e (patch) | |
tree | 669263f8f423f073f133b68787079cf8fecb8411 /lldb/packages/Python/lldbsuite/test/expression_command/context-object-objc | |
parent | de5220ed5e5ab1f7064e9bae57d7b4b8887277fa (diff) | |
download | bcm5719-llvm-40624a085c03fb6d41834885d41f7158ab72950e.tar.gz bcm5719-llvm-40624a085c03fb6d41834885d41f7158ab72950e.zip |
[Expressions] Add support of expressions evaluation in some object's context
Summary:
This patch adds support of expression evaluation in a context of some object.
Consider the following example:
```
struct S {
int a = 11;
int b = 12;
};
int main() {
S s;
int a = 1;
int b = 2;
// We have stopped here
return 0;
}
```
This patch allows to do something like that:
```
lldb.frame.FindVariable("s").EvaluateExpression("a + b")
```
and the result will be `33` (not `3`) because fields `a` and `b` of `s` will be
used (not locals `a` and `b`).
This is achieved by replacing of `this` type and object for the expression. This
has some limitations: an expression can be evaluated only for values located in
the debuggee process memory (they must have an address of `eAddressTypeLoad`
type).
Reviewers: teemperor, clayborg, jingham, zturner, labath, davide, spyffe, serge-sans-paille
Reviewed By: jingham
Subscribers: abidh, lldb-commits, leonid.mashinskiy
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D55318
llvm-svn: 353149
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test/expression_command/context-object-objc')
3 files changed, 131 insertions, 0 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/context-object-objc/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/context-object-objc/Makefile new file mode 100644 index 00000000000..b6592745356 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/expression_command/context-object-objc/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules +LDFLAGS += -framework Foundation diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/context-object-objc/TestContextObjectObjc.py b/lldb/packages/Python/lldbsuite/test/expression_command/context-object-objc/TestContextObjectObjc.py new file mode 100644 index 00000000000..4ae4fd8680d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/expression_command/context-object-objc/TestContextObjectObjc.py @@ -0,0 +1,78 @@ +""" +Tests expression evaluation in context of an objc class. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +class ContextObjectObjcTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test_context_object_objc(self): + """Tests expression evaluation in context of an objc class.""" + self.build() + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, '// Break here', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) + + # + # Test objc class variable + # + + obj_val = frame.FindVariable("objcClass") + self.assertTrue(obj_val.IsValid()) + obj_val = obj_val.Dereference() + self.assertTrue(obj_val.IsValid()) + + # Test an empty expression evaluation + value = obj_val.EvaluateExpression("") + self.assertFalse(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + # Test retrieving of a field (not a local with the same name) + value = obj_val.EvaluateExpression("field") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 1111) + + # Test if the self pointer is properly evaluated + + # Test retrieving of an objcClass's property through the self pointer + value = obj_val.EvaluateExpression("self.property") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 2222) + + # Test objcClass's methods evaluation through the self pointer + value = obj_val.EvaluateExpression("[self method]") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 3333) + + # Test if we can use a computation result reference object correctly + + obj_val = frame.EvaluateExpression("[ObjcClass createNew]") + self.assertTrue(obj_val.IsValid()) + obj_val = obj_val.Dereference() + self.assertTrue(obj_val.IsValid()) + + # Test an expression evaluation on it + value = obj_val.EvaluateExpression("1") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + + # Test retrieving of a field on it + value = obj_val.EvaluateExpression("field") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 1111) + + def setUp(self): + TestBase.setUp(self) + + self.main_source = "main.m" + self.main_source_spec = lldb.SBFileSpec(self.main_source) diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/context-object-objc/main.m b/lldb/packages/Python/lldbsuite/test/expression_command/context-object-objc/main.m new file mode 100644 index 00000000000..5c495b24894 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/expression_command/context-object-objc/main.m @@ -0,0 +1,47 @@ +#import <Foundation/Foundation.h> + +@interface ObjcClass : NSObject { + int field; +} + +@property int property; + ++(ObjcClass*)createNew; + +-(id)init; + +-(int)method; + +@end + +@implementation ObjcClass + ++(ObjcClass*)createNew { + return [ObjcClass new]; +} + +-(id)init { + self = [super init]; + if (self) { + field = 1111; + _property = 2222; + } + return self; +} + +-(int)method { + return 3333; +} + +@end + +int main() +{ + @autoreleasepool { + ObjcClass* objcClass = [ObjcClass new]; + + int field = 4444; + + return 0; // Break here + } +} |