1"""
2Tests that C++ member and static variables have correct layout and scope.
3"""
4
5
6
7import unittest2
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class TestCase(TestBase):
15
16    # We fail to lookup static members on Windows.
17    @expectedFailureAll(oslist=["windows"])
18    def test_access_from_main(self):
19        self.build()
20        lldbutil.run_to_source_breakpoint(self, "// stop in main", lldb.SBFileSpec("main.cpp"))
21
22        self.expect_expr("my_a.m_a", result_type="short", result_value="1")
23        self.expect_expr("my_a.s_b", result_type="long", result_value="2")
24        self.expect_expr("my_a.s_c", result_type="int", result_value="3")
25
26    # We fail to lookup static members on Windows.
27    @expectedFailureAll(oslist=["windows"])
28    def test_access_from_member_function(self):
29        self.build()
30        lldbutil.run_to_source_breakpoint(self, "// stop in member function", lldb.SBFileSpec("main.cpp"))
31        self.expect_expr("m_a", result_type="short", result_value="1")
32        self.expect_expr("s_b", result_type="long", result_value="2")
33        self.expect_expr("s_c", result_type="int", result_value="3")
34
35    # Currently lookups find variables that are in any scope.
36    @expectedFailureAll()
37    def test_access_without_scope(self):
38        self.build()
39        self.createTestTarget()
40        self.expect("expression s_c", error=True,
41                    startstr="error: use of undeclared identifier 's_d'")
42
43    # We fail to lookup static members on Windows.
44    @expectedFailureAll(oslist=["windows"])
45    def test_no_crash_in_IR_arithmetic(self):
46        """
47        Test that LLDB doesn't crash on evaluating specific expression involving
48        pointer arithmetic and taking the address of a static class member.
49        See https://bugs.llvm.org/show_bug.cgi?id=52449
50        """
51        self.build()
52        lldbutil.run_to_source_breakpoint(self, "// stop in main", lldb.SBFileSpec("main.cpp"))
53
54        # This expression contains the following IR code:
55        # ... i64 ptrtoint (i32* @_ZN1A3s_cE to i64)) ...
56        expr = "(int*)100 + (long long)(&A::s_c)"
57
58        # The IR interpreter doesn't support non-const operands to the
59        # `GetElementPtr` IR instruction, so verify that it correctly fails to
60        # evaluate expression.
61        opts = lldb.SBExpressionOptions()
62        opts.SetAllowJIT(False)
63        value = self.target().EvaluateExpression(expr, opts)
64        self.assertTrue(value.GetError().Fail())
65        self.assertIn(
66            "Can't evaluate the expression without a running target",
67            value.GetError().GetCString())
68
69        # Evaluating the expression via JIT should work fine.
70        value = self.target().EvaluateExpression(expr)
71        self.assertSuccess(value.GetError())
72
73    def test_IR_interpreter_can_handle_getelementptr_constants_args(self):
74        self.build()
75        lldbutil.run_to_source_breakpoint(self, "// stop in main", lldb.SBFileSpec("main.cpp"))
76
77        # This expression contains the following IR code:
78        # ... getelementptr inbounds [2 x i32], [2 x i32]* %4, i64 0, i64 0
79        expr = "arr[0]"
80
81        # The IR interpreter supports const operands to the `GetElementPtr` IR
82        # instruction, so it should be able to evaluate expression without JIT.
83        opts = lldb.SBExpressionOptions()
84        opts.SetAllowJIT(False)
85        value = self.target().EvaluateExpression(expr, opts)
86        self.assertSuccess(value.GetError())
87