aboutsummaryrefslogtreecommitdiff
path: root/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py
blob: b3bed43c75873771e9cedca539c0c48b2650d49f (plain)
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
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


class ExprDefinitionInDylibTestCase(TestBase):

    @skipIf(
        compiler="clang",
        compiler_version=["<", "22"],
        bugnumber="Required Clang flag not supported",
    )
    @skipIfWindows
    def test_with_structor_linkage_names(self):
        """
        Tests that we can call functions whose definition
        is in a different LLDB module than it's declaration.
        """
        self.build(dictionary={"CXXFLAGS_EXTRAS": "-gstructor-decl-linkage-names"})

        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
        self.assertTrue(target, VALID_TARGET)

        env = self.registerSharedLibrariesWithTarget(target, ["lib"])

        breakpoint = lldbutil.run_break_set_by_file_and_line(
            self, "main.cpp", line_number("main.cpp", "return")
        )

        process = target.LaunchSimple(None, env, self.get_process_working_directory())

        self.assertIsNotNone(
            lldbutil.get_one_thread_stopped_at_breakpoint_id(self.process(), breakpoint)
        )

        self.expect_expr("f.method()", result_value="-72", result_type="int")

        self.expect_expr("Foo(10)", result_type="Foo")

        self.expect_expr("Base()", result_type="Base")

        self.expect_expr("Bar()", result_type="Bar")

        # Test a more complex setup: expression that has a three bases:
        # 1. definition is in local module
        # 2. definition is in different module
        # 3. definition is in expression context (and has it's own virtual base)
        self.expect_expr(
            "struct ExprBase : virtual Foo { int z; ExprBase() : Foo(11) { z = x; } }; struct Expr : virtual Local, virtual Foo, virtual ExprBase { int w; Expr() : Local(), Foo(12), ExprBase() { w = y; } }; Expr tmp; tmp",
            result_type="Expr",
            result_children=[
                ValueCheck(
                    name="Local",
                    children=[
                        ValueCheck(
                            name="Foo", children=[ValueCheck(name="x", value="12")]
                        ),
                        ValueCheck(name="y", value="12"),
                    ],
                ),
                ValueCheck(name="Foo", children=[ValueCheck(name="x", value="12")]),
                ValueCheck(
                    name="ExprBase",
                    children=[
                        ValueCheck(
                            name="Foo", children=[ValueCheck(name="x", value="12")]
                        ),
                        ValueCheck(name="z", value="12"),
                    ],
                ),
                ValueCheck(name="w", value="12"),
            ],
        )

    @skipIfWindows
    def test_no_structor_linkage_names(self):
        """
        Tests that if structor declarations don't have linkage names, we can't
        call ABI-tagged constructors. But non-tagged ones are fine.
        """
        # In older versions of Clang the -gno-structor-decl-linkage-names
        # behaviour was the default.
        if self.expectedCompiler(["clang"]) and self.expectedCompilerVersion(
            [">=", "22.0"]
        ):
            self.build(
                dictionary={"CXXFLAGS_EXTRAS": "-gno-structor-decl-linkage-names"}
            )
        else:
            self.build()

        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
        self.assertTrue(target, VALID_TARGET)

        env = self.registerSharedLibrariesWithTarget(target, ["lib"])

        breakpoint = lldbutil.run_break_set_by_file_and_line(
            self, "main.cpp", line_number("main.cpp", "return")
        )

        process = target.LaunchSimple(None, env, self.get_process_working_directory())

        self.assertIsNotNone(
            lldbutil.get_one_thread_stopped_at_breakpoint_id(self.process(), breakpoint)
        )

        self.expect_expr("f.method()", result_value="-72", result_type="int")

        self.expect_expr("Foo(10)", result_type="Foo")

        self.expect("expr Base()", error=True)

        self.expect("expr Bar()", error=True)