File: TestExprInsideLambdas.py

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (137 lines) | stat: -rw-r--r-- 5,726 bytes parent folder | download | duplicates (10)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
""" 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):
    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 '(unnamed class)' 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"),
        )