File: TestExprInsideLambdas.py

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (124 lines) | stat: -rw-r--r-- 5,727 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
""" Test that evaluating expressions from within C++ lambdas works
    Particularly, we test the case of capturing "this" and
    using members of the captured object in expression evaluation
    while we're on a breakpoint inside a lambda.
"""


import lldb
from lldbsuite.test.lldbtest import *


class ExprInsideLambdaTestCase(TestBase):

    mydir = TestBase.compute_mydir(__file__)

    def expectExprError(self, expr : str, expected : str):
        frame = self.thread.GetFrameAtIndex(0)
        value = frame.EvaluateExpression(expr)
        errmsg = value.GetError().GetCString()
        self.assertIn(expected, errmsg)

    def test_expr_inside_lambda(self):
        """Test that lldb evaluating expressions inside lambda expressions works correctly."""
        self.build()
        (target, process, self.thread, bkpt) = \
                lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.cpp"))

        # Inside 'Foo::method'

        # Check access to captured 'this'
        self.expect_expr("class_var", result_type="int", result_value="109")
        self.expect_expr("this->class_var", result_type="int", result_value="109")

        # Check that captured shadowed variables take preference over the
        # corresponding member variable
        self.expect_expr("shadowed", result_type="int", result_value="5")
        self.expect_expr("this->shadowed", result_type="int", result_value="-137")

        # Check access to local captures
        self.expect_expr("local_var", result_type="int", result_value="137")
        self.expect_expr("*class_ptr", result_type="int", result_value="137")

        # Check access to base class variables
        self.expect_expr("base_var", result_type="int", result_value="14")
        self.expect_expr("base_base_var", result_type="int", result_value="11")

        # Check access to global variable
        self.expect_expr("global_var", result_type="int", result_value="-5")

        # Check access to multiple captures/member variables
        self.expect_expr("(shadowed + this->shadowed) * (base_base_var + local_var - class_var)",
                         result_type="int", result_value="-5148")

        # Check base-class function call
        self.expect_expr("baz_virt()", result_type="int", result_value="2")
        self.expect_expr("base_var", result_type="int", result_value="14")
        self.expect_expr("this->shadowed", result_type="int", result_value="-1")
        
        # 'p this' should yield 'struct Foo*'
        frame = self.thread.GetFrameAtIndex(0)
        outer_class_addr = frame.GetValueForVariablePath("this->this")
        self.expect_expr("this", result_value=outer_class_addr.GetValue())

        lldbutil.continue_to_breakpoint(process, bkpt)

        # Inside 'nested_lambda'
        
        # Check access to captured 'this'. Should still be 'struct Foo*'
        self.expect_expr("class_var", result_type="int", result_value="109")
        self.expect_expr("global_var", result_type="int", result_value="-5")
        self.expect_expr("this", result_value=outer_class_addr.GetValue())

        # Check access to captures
        self.expect_expr("lambda_local_var", result_type="int", result_value="5")
        self.expect_expr("local_var", result_type="int", result_value="137")

        # Check access to variable in previous frame which we didn't capture
        self.expectExprError("local_var_copy", "use of undeclared identifier")

        lldbutil.continue_to_breakpoint(process, bkpt)

        # By-ref mutates source variable
        self.expect_expr("lambda_local_var", result_type="int", result_value="0")

        # By-value doesn't mutate source variable
        self.expect_expr("local_var_copy", result_type="int", result_value="136")
        self.expect_expr("local_var", result_type="int", result_value="137")

        lldbutil.continue_to_breakpoint(process, bkpt)

        # Inside 'LocalLambdaClass::inner_method'

        # Check access to captured 'this'
        self.expect_expr("lambda_class_local", result_type="int", result_value="-12345")
        self.expect_expr("this->lambda_class_local", result_type="int", result_value="-12345")
        self.expect_expr("outer_ptr->class_var", result_type="int", result_value="109")

        # 'p this' should yield 'struct LocalLambdaClass*'
        frame = self.thread.GetFrameAtIndex(0)
        local_class_addr = frame.GetValueForVariablePath("this->this")
        self.assertNotEqual(local_class_addr, outer_class_addr)
        self.expect_expr("this", result_value=local_class_addr.GetValue())

        # Can still access global variable
        self.expect_expr("global_var", result_type="int", result_value="-5")

        # Check access to outer top-level structure's members
        self.expectExprError("class_var", ("use of non-static data member"
                                           " 'class_var' of 'Foo' from nested type"))

        self.expectExprError("base_var", ("use of non-static data member"
                                           " 'base_var'"))

        self.expectExprError("local_var", ("use of non-static data member 'local_var'"
                                           " of '' from nested type 'LocalLambdaClass'"))

        # Inside non_capturing_method
        lldbutil.continue_to_breakpoint(process, bkpt)
        self.expect_expr("local", result_type="int", result_value="5")
        self.expect_expr("local2", result_type="int", result_value="10")
        self.expect_expr("local2 * local", result_type="int", result_value="50")

        self.expectExprError("class_var", ("use of non-static data member"
                                           " 'class_var' of 'Foo' from nested type"))