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