1 """ Test that evaluating expressions from within C++ lambdas works
2 Particularly, we test the case of capturing "this" and
3 using members of the captured object in expression evaluation
4 while we're on a breakpoint inside a lambda.
9 from lldbsuite
.test
.lldbtest
import *
12 class 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
)
19 def test_expr_inside_lambda(self
):
20 """Test that lldb evaluating expressions inside lambda expressions works correctly."""
22 (target
, process
, self
.thread
, bkpt
) = lldbutil
.run_to_source_breakpoint(
23 self
, "break here", lldb
.SBFileSpec("main.cpp")
26 # Inside 'Foo::method'
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")
32 # Check that captured shadowed variables take preference over the
33 # corresponding member variable
34 self
.expect_expr("shadowed", result_type
="int", result_value
="5")
35 self
.expect_expr("this->shadowed", result_type
="int", result_value
="-137")
37 # Check access to local captures
38 self
.expect_expr("local_var", result_type
="int", result_value
="137")
39 self
.expect_expr("*class_ptr", result_type
="int", result_value
="137")
41 # Check access to base class variables
42 self
.expect_expr("base_var", result_type
="int", result_value
="14")
43 self
.expect_expr("base_base_var", result_type
="int", result_value
="11")
45 # Check access to global variable
46 self
.expect_expr("global_var", result_type
="int", result_value
="-5")
48 # Check access to multiple captures/member variables
50 "(shadowed + this->shadowed) * (base_base_var + local_var - class_var)",
55 # Check base-class function call
56 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")
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())
65 lldbutil
.continue_to_breakpoint(process
, bkpt
)
67 # Inside 'nested_lambda'
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())
74 # Check access to captures
75 self
.expect_expr("lambda_local_var", result_type
="int", result_value
="5")
76 self
.expect_expr("local_var", result_type
="int", result_value
="137")
78 # Check access to variable in previous frame which we didn't capture
79 self
.expectExprError("local_var_copy", "use of undeclared identifier")
81 lldbutil
.continue_to_breakpoint(process
, bkpt
)
83 # By-ref mutates source variable
84 self
.expect_expr("lambda_local_var", result_type
="int", result_value
="0")
86 # By-value doesn't mutate source variable
87 self
.expect_expr("local_var_copy", result_type
="int", result_value
="136")
88 self
.expect_expr("local_var", result_type
="int", result_value
="137")
90 lldbutil
.continue_to_breakpoint(process
, bkpt
)
92 # Inside 'LocalLambdaClass::inner_method'
94 # Check access to captured 'this'
95 self
.expect_expr("lambda_class_local", result_type
="int", result_value
="-12345")
97 "this->lambda_class_local", result_type
="int", result_value
="-12345"
99 self
.expect_expr("outer_ptr->class_var", result_type
="int", result_value
="109")
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())
107 # Can still access global variable
108 self
.expect_expr("global_var", result_type
="int", result_value
="-5")
110 # Check access to outer top-level structure's members
111 self
.expectExprError(
113 ("use of non-static data member" " 'class_var' of 'Foo' from nested type"),
116 self
.expectExprError(
117 "base_var", ("use of non-static data member" " 'base_var'")
120 self
.expectExprError(
123 "use of non-static data member 'local_var'"
124 " of '(unnamed class)' from nested type 'LocalLambdaClass'"
128 # Inside non_capturing_method
129 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")
134 self
.expectExprError(
136 ("use of non-static data member" " 'class_var' of 'Foo' from nested type"),