138 lines · python
1""" Test that evaluating expressions from within C++ lambdas works2 Particularly, we test the case of capturing "this" and3 using members of the captured object in expression evaluation4 while we're on a breakpoint inside a lambda.5"""6 7 8import lldb9from lldbsuite.test.lldbtest import *10 11 12class ExprInsideLambdaTestCase(TestBase):13 def expectExprError(self, expr: str, expected: str):14 frame = self.thread.GetFrameAtIndex(0)15 value = frame.EvaluateExpression(expr)16 errmsg = value.GetError().GetCString()17 self.assertIn(expected, errmsg)18 19 def test_expr_inside_lambda(self):20 """Test that lldb evaluating expressions inside lambda expressions works correctly."""21 self.build()22 (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(23 self, "break here", lldb.SBFileSpec("main.cpp")24 )25 26 # Inside 'Foo::method'27 28 # Check access to captured 'this'29 self.expect_expr("class_var", result_type="int", result_value="109")30 self.expect_expr("this->class_var", result_type="int", result_value="109")31 32 # Check that captured shadowed variables take preference over the33 # corresponding member variable34 self.expect_expr("shadowed", result_type="int", result_value="5")35 self.expect_expr("this->shadowed", result_type="int", result_value="-137")36 37 # Check access to local captures38 self.expect_expr("local_var", result_type="int", result_value="137")39 self.expect_expr("*class_ptr", result_type="int", result_value="137")40 41 # Check access to base class variables42 self.expect_expr("base_var", result_type="int", result_value="14")43 self.expect_expr("base_base_var", result_type="int", result_value="11")44 45 # Check access to global variable46 self.expect_expr("global_var", result_type="int", result_value="-5")47 48 # Check access to multiple captures/member variables49 self.expect_expr(50 "(shadowed + this->shadowed) * (base_base_var + local_var - class_var)",51 result_type="int",52 result_value="-5148",53 )54 55 # Check base-class function call56 self.expect_expr("baz_virt()", result_type="int", result_value="2")57 self.expect_expr("base_var", result_type="int", result_value="14")58 self.expect_expr("this->shadowed", result_type="int", result_value="-1")59 60 # 'p this' should yield 'struct Foo*'61 frame = self.thread.GetFrameAtIndex(0)62 outer_class_addr = frame.GetValueForVariablePath("this->this")63 self.expect_expr("this", result_value=outer_class_addr.GetValue())64 65 lldbutil.continue_to_breakpoint(process, bkpt)66 67 # Inside 'nested_lambda'68 69 # Check access to captured 'this'. Should still be 'struct Foo*'70 self.expect_expr("class_var", result_type="int", result_value="109")71 self.expect_expr("global_var", result_type="int", result_value="-5")72 self.expect_expr("this", result_value=outer_class_addr.GetValue())73 74 # Check access to captures75 self.expect_expr("lambda_local_var", result_type="int", result_value="5")76 self.expect_expr("local_var", result_type="int", result_value="137")77 78 # Check access to variable in previous frame which we didn't capture79 self.expectExprError("local_var_copy", "use of undeclared identifier")80 81 lldbutil.continue_to_breakpoint(process, bkpt)82 83 # By-ref mutates source variable84 self.expect_expr("lambda_local_var", result_type="int", result_value="0")85 86 # By-value doesn't mutate source variable87 self.expect_expr("local_var_copy", result_type="int", result_value="136")88 self.expect_expr("local_var", result_type="int", result_value="137")89 90 lldbutil.continue_to_breakpoint(process, bkpt)91 92 # Inside 'LocalLambdaClass::inner_method'93 94 # Check access to captured 'this'95 self.expect_expr("lambda_class_local", result_type="int", result_value="-12345")96 self.expect_expr(97 "this->lambda_class_local", result_type="int", result_value="-12345"98 )99 self.expect_expr("outer_ptr->class_var", result_type="int", result_value="109")100 101 # 'p this' should yield 'struct LocalLambdaClass*'102 frame = self.thread.GetFrameAtIndex(0)103 local_class_addr = frame.GetValueForVariablePath("this->this")104 self.assertNotEqual(local_class_addr, outer_class_addr)105 self.expect_expr("this", result_value=local_class_addr.GetValue())106 107 # Can still access global variable108 self.expect_expr("global_var", result_type="int", result_value="-5")109 110 # Check access to outer top-level structure's members111 self.expectExprError(112 "class_var",113 ("use of non-static data member" " 'class_var' of 'Foo' from nested type"),114 )115 116 self.expectExprError(117 "base_var", ("use of non-static data member" " 'base_var'")118 )119 120 self.expectExprError(121 "local_var",122 (123 "use of non-static data member 'local_var'"124 " of '(unnamed class)' from nested type 'LocalLambdaClass'"125 ),126 )127 128 # Inside non_capturing_method129 lldbutil.continue_to_breakpoint(process, bkpt)130 self.expect_expr("local", result_type="int", result_value="5")131 self.expect_expr("local2", result_type="int", result_value="10")132 self.expect_expr("local2 * local", result_type="int", result_value="50")133 134 self.expectExprError(135 "class_var",136 ("use of non-static data member" " 'class_var' of 'Foo' from nested type"),137 )138