18184b252SMichael Buch""" Test that evaluating expressions from within C++ lambdas works 28184b252SMichael Buch Particularly, we test the case of capturing "this" and 38184b252SMichael Buch using members of the captured object in expression evaluation 48184b252SMichael Buch while we're on a breakpoint inside a lambda. 58184b252SMichael Buch""" 68184b252SMichael Buch 78184b252SMichael Buch 88184b252SMichael Buchimport lldb 98184b252SMichael Buchfrom lldbsuite.test.lldbtest import * 108184b252SMichael Buch 118184b252SMichael Buch 128184b252SMichael Buchclass ExprInsideLambdaTestCase(TestBase): 138184b252SMichael Buch def expectExprError(self, expr: str, expected: str): 148184b252SMichael Buch frame = self.thread.GetFrameAtIndex(0) 158184b252SMichael Buch value = frame.EvaluateExpression(expr) 168184b252SMichael Buch errmsg = value.GetError().GetCString() 178184b252SMichael Buch self.assertIn(expected, errmsg) 188184b252SMichael Buch 198184b252SMichael Buch def test_expr_inside_lambda(self): 208184b252SMichael Buch """Test that lldb evaluating expressions inside lambda expressions works correctly.""" 218184b252SMichael Buch self.build() 22*2238dcc3SJonas Devlieghere (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint( 23*2238dcc3SJonas Devlieghere self, "break here", lldb.SBFileSpec("main.cpp") 24*2238dcc3SJonas Devlieghere ) 258184b252SMichael Buch 268184b252SMichael Buch # Inside 'Foo::method' 278184b252SMichael Buch 288184b252SMichael Buch # Check access to captured 'this' 298184b252SMichael Buch self.expect_expr("class_var", result_type="int", result_value="109") 308184b252SMichael Buch self.expect_expr("this->class_var", result_type="int", result_value="109") 318184b252SMichael Buch 328184b252SMichael Buch # Check that captured shadowed variables take preference over the 338184b252SMichael Buch # corresponding member variable 348184b252SMichael Buch self.expect_expr("shadowed", result_type="int", result_value="5") 358184b252SMichael Buch self.expect_expr("this->shadowed", result_type="int", result_value="-137") 368184b252SMichael Buch 378184b252SMichael Buch # Check access to local captures 388184b252SMichael Buch self.expect_expr("local_var", result_type="int", result_value="137") 398184b252SMichael Buch self.expect_expr("*class_ptr", result_type="int", result_value="137") 408184b252SMichael Buch 418184b252SMichael Buch # Check access to base class variables 428184b252SMichael Buch self.expect_expr("base_var", result_type="int", result_value="14") 438184b252SMichael Buch self.expect_expr("base_base_var", result_type="int", result_value="11") 448184b252SMichael Buch 458184b252SMichael Buch # Check access to global variable 468184b252SMichael Buch self.expect_expr("global_var", result_type="int", result_value="-5") 478184b252SMichael Buch 488184b252SMichael Buch # Check access to multiple captures/member variables 49*2238dcc3SJonas Devlieghere self.expect_expr( 50*2238dcc3SJonas Devlieghere "(shadowed + this->shadowed) * (base_base_var + local_var - class_var)", 51*2238dcc3SJonas Devlieghere result_type="int", 52*2238dcc3SJonas Devlieghere result_value="-5148", 53*2238dcc3SJonas Devlieghere ) 548184b252SMichael Buch 558184b252SMichael Buch # Check base-class function call 568184b252SMichael Buch self.expect_expr("baz_virt()", result_type="int", result_value="2") 578184b252SMichael Buch self.expect_expr("base_var", result_type="int", result_value="14") 588184b252SMichael Buch self.expect_expr("this->shadowed", result_type="int", result_value="-1") 598184b252SMichael Buch 608184b252SMichael Buch # 'p this' should yield 'struct Foo*' 618184b252SMichael Buch frame = self.thread.GetFrameAtIndex(0) 628184b252SMichael Buch outer_class_addr = frame.GetValueForVariablePath("this->this") 638184b252SMichael Buch self.expect_expr("this", result_value=outer_class_addr.GetValue()) 648184b252SMichael Buch 658184b252SMichael Buch lldbutil.continue_to_breakpoint(process, bkpt) 668184b252SMichael Buch 678184b252SMichael Buch # Inside 'nested_lambda' 688184b252SMichael Buch 698184b252SMichael Buch # Check access to captured 'this'. Should still be 'struct Foo*' 708184b252SMichael Buch self.expect_expr("class_var", result_type="int", result_value="109") 718184b252SMichael Buch self.expect_expr("global_var", result_type="int", result_value="-5") 728184b252SMichael Buch self.expect_expr("this", result_value=outer_class_addr.GetValue()) 738184b252SMichael Buch 748184b252SMichael Buch # Check access to captures 758184b252SMichael Buch self.expect_expr("lambda_local_var", result_type="int", result_value="5") 768184b252SMichael Buch self.expect_expr("local_var", result_type="int", result_value="137") 778184b252SMichael Buch 788184b252SMichael Buch # Check access to variable in previous frame which we didn't capture 798184b252SMichael Buch self.expectExprError("local_var_copy", "use of undeclared identifier") 808184b252SMichael Buch 818184b252SMichael Buch lldbutil.continue_to_breakpoint(process, bkpt) 828184b252SMichael Buch 838184b252SMichael Buch # By-ref mutates source variable 848184b252SMichael Buch self.expect_expr("lambda_local_var", result_type="int", result_value="0") 858184b252SMichael Buch 868184b252SMichael Buch # By-value doesn't mutate source variable 878184b252SMichael Buch self.expect_expr("local_var_copy", result_type="int", result_value="136") 888184b252SMichael Buch self.expect_expr("local_var", result_type="int", result_value="137") 898184b252SMichael Buch 908184b252SMichael Buch lldbutil.continue_to_breakpoint(process, bkpt) 918184b252SMichael Buch 928184b252SMichael Buch # Inside 'LocalLambdaClass::inner_method' 938184b252SMichael Buch 948184b252SMichael Buch # Check access to captured 'this' 958184b252SMichael Buch self.expect_expr("lambda_class_local", result_type="int", result_value="-12345") 96*2238dcc3SJonas Devlieghere self.expect_expr( 97*2238dcc3SJonas Devlieghere "this->lambda_class_local", result_type="int", result_value="-12345" 98*2238dcc3SJonas Devlieghere ) 998184b252SMichael Buch self.expect_expr("outer_ptr->class_var", result_type="int", result_value="109") 1008184b252SMichael Buch 1018184b252SMichael Buch # 'p this' should yield 'struct LocalLambdaClass*' 1028184b252SMichael Buch frame = self.thread.GetFrameAtIndex(0) 1038184b252SMichael Buch local_class_addr = frame.GetValueForVariablePath("this->this") 1048184b252SMichael Buch self.assertNotEqual(local_class_addr, outer_class_addr) 1058184b252SMichael Buch self.expect_expr("this", result_value=local_class_addr.GetValue()) 1068184b252SMichael Buch 1078184b252SMichael Buch # Can still access global variable 1088184b252SMichael Buch self.expect_expr("global_var", result_type="int", result_value="-5") 1098184b252SMichael Buch 1108184b252SMichael Buch # Check access to outer top-level structure's members 111*2238dcc3SJonas Devlieghere self.expectExprError( 112*2238dcc3SJonas Devlieghere "class_var", 113*2238dcc3SJonas Devlieghere ("use of non-static data member" " 'class_var' of 'Foo' from nested type"), 114*2238dcc3SJonas Devlieghere ) 1158184b252SMichael Buch 116*2238dcc3SJonas Devlieghere self.expectExprError( 117*2238dcc3SJonas Devlieghere "base_var", ("use of non-static data member" " 'base_var'") 118*2238dcc3SJonas Devlieghere ) 1198184b252SMichael Buch 120*2238dcc3SJonas Devlieghere self.expectExprError( 121*2238dcc3SJonas Devlieghere "local_var", 122*2238dcc3SJonas Devlieghere ( 123*2238dcc3SJonas Devlieghere "use of non-static data member 'local_var'" 124*2238dcc3SJonas Devlieghere " of '(unnamed class)' from nested type 'LocalLambdaClass'" 125*2238dcc3SJonas Devlieghere ), 126*2238dcc3SJonas Devlieghere ) 1278184b252SMichael Buch 1288184b252SMichael Buch # Inside non_capturing_method 1298184b252SMichael Buch lldbutil.continue_to_breakpoint(process, bkpt) 1308184b252SMichael Buch self.expect_expr("local", result_type="int", result_value="5") 1318184b252SMichael Buch self.expect_expr("local2", result_type="int", result_value="10") 1328184b252SMichael Buch self.expect_expr("local2 * local", result_type="int", result_value="50") 1338184b252SMichael Buch 134*2238dcc3SJonas Devlieghere self.expectExprError( 135*2238dcc3SJonas Devlieghere "class_var", 136*2238dcc3SJonas Devlieghere ("use of non-static data member" " 'class_var' of 'Foo' from nested type"), 137*2238dcc3SJonas Devlieghere ) 138