1"""
2Test that C++ template classes that have integer parameters work correctly.
3
4We must reconstruct the types correctly so the template types are correct
5and display correctly, and also make sure the expression parser works and
6is able the find all needed functions when evaluating expressions
7"""
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class TemplateArgsTestCase(TestBase):
15
16    mydir = TestBase.compute_mydir(__file__)
17
18    def prepareProcess(self):
19        self.build()
20
21        # Create a target by the debugger.
22        exe = self.getBuildArtifact("a.out")
23        target = self.dbg.CreateTarget(exe)
24        self.assertTrue(target, VALID_TARGET)
25
26        # Set breakpoints inside and outside methods that take pointers to the
27        # containing struct.
28        line = line_number('main.cpp', '// Breakpoint 1')
29        lldbutil.run_break_set_by_file_and_line(
30            self, "main.cpp", line, num_expected_locations=1, loc_exact=True)
31
32        arguments = None
33        environment = None
34
35        # Now launch the process, and do not stop at entry point.
36        process = target.LaunchSimple(
37            arguments, environment, self.get_process_working_directory())
38        self.assertTrue(process, PROCESS_IS_VALID)
39
40        # Get the thread of the process
41        self.assertTrue(
42            process.GetState() == lldb.eStateStopped,
43            PROCESS_STOPPED)
44        thread = lldbutil.get_stopped_thread(
45            process, lldb.eStopReasonBreakpoint)
46
47        # Get frame for current thread
48        return thread.GetSelectedFrame()
49
50    def test_integer_args(self):
51        frame = self.prepareProcess()
52
53        testpos = frame.FindVariable('testpos')
54        self.assertTrue(
55            testpos.IsValid(),
56            'make sure we find a local variabble named "testpos"')
57        self.assertEquals(testpos.GetType().GetName(), 'TestObj<1>')
58
59        expr_result = frame.EvaluateExpression("testpos.getArg()")
60        self.assertTrue(
61            expr_result.IsValid(),
62            'got a valid expression result from expression "testpos.getArg()"')
63        self.assertEquals(expr_result.GetValue(), "1", "testpos.getArg() == 1")
64        self.assertTrue(
65            expr_result.GetType().GetName() == "int",
66            'expr_result.GetType().GetName() == "int"')
67
68        testneg = frame.FindVariable('testneg')
69        self.assertTrue(
70            testneg.IsValid(),
71            'make sure we find a local variabble named "testneg"')
72        self.assertEquals(testneg.GetType().GetName(), 'TestObj<-1>')
73
74        expr_result = frame.EvaluateExpression("testneg.getArg()")
75        self.assertTrue(
76            expr_result.IsValid(),
77            'got a valid expression result from expression "testneg.getArg()"')
78        self.assertTrue(
79            expr_result.GetValue() == "-1",
80            "testneg.getArg() == -1")
81        self.assertTrue(
82            expr_result.GetType().GetName() == "int",
83            'expr_result.GetType().GetName() == "int"')
84
85    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")
86    def test_template_template_args(self):
87        frame = self.prepareProcess()
88
89        c1 = frame.FindVariable('c1')
90        self.assertTrue(
91            c1.IsValid(),
92            'make sure we find a local variabble named "c1"')
93        self.assertEquals(c1.GetType().GetName(), 'C<float, T1>')
94        f1 = c1.GetChildMemberWithName("V").GetChildAtIndex(0).GetChildMemberWithName("f")
95        self.assertEquals(f1.GetType().GetName(), 'float')
96        self.assertEquals(f1.GetValue(), '1.5')
97
98        c2 = frame.FindVariable('c2')
99        self.assertTrue(
100            c2.IsValid(),
101            'make sure we find a local variabble named "c2"')
102        self.assertEquals(c2.GetType().GetName(), 'C<double, T1, T2>')
103        f2 = c2.GetChildMemberWithName("V").GetChildAtIndex(0).GetChildMemberWithName("f")
104        self.assertEquals(f2.GetType().GetName(), 'double')
105        self.assertEquals(f2.GetValue(), '1.5')
106        f3 = c2.GetChildMemberWithName("V").GetChildAtIndex(1).GetChildMemberWithName("f")
107        self.assertEquals(f3.GetType().GetName(), 'double')
108        self.assertEquals(f3.GetValue(), '2.5')
109        f4 = c2.GetChildMemberWithName("V").GetChildAtIndex(1).GetChildMemberWithName("i")
110        self.assertEquals(f4.GetType().GetName(), 'int')
111        self.assertEquals(f4.GetValue(), '42')
112
113    # Gcc does not generate the necessary DWARF attribute for enum template
114    # parameters.
115    @expectedFailureAll(bugnumber="llvm.org/pr28354", compiler="gcc")
116    @skipIf(dwarf_version=['<', '4'])
117    def test_enum_args(self):
118        frame = self.prepareProcess()
119
120        # Make sure "member" can be displayed and also used in an expression
121        # correctly
122        member = frame.FindVariable('member')
123        self.assertTrue(
124            member.IsValid(),
125            'make sure we find a local variabble named "member"')
126        self.assertTrue(member.GetType().GetName() ==
127                        'EnumTemplate<EnumType::Member>')
128
129        expr_result = frame.EvaluateExpression("member.getMember()")
130        self.assertTrue(
131            expr_result.IsValid(),
132            'got a valid expression result from expression "member.getMember()"')
133        self.assertTrue(
134            expr_result.GetValue() == "123",
135            "member.getMember() == 123")
136        self.assertTrue(
137            expr_result.GetType().GetName() == "int",
138            'expr_result.GetType().GetName() == "int"')
139
140        # Make sure "subclass" can be displayed and also used in an expression
141        # correctly
142        subclass = frame.FindVariable('subclass')
143        self.assertTrue(
144            subclass.IsValid(),
145            'make sure we find a local variabble named "subclass"')
146        self.assertTrue(subclass.GetType().GetName() ==
147                        'EnumTemplate<EnumType::Subclass>')
148
149        expr_result = frame.EvaluateExpression("subclass.getMember()")
150        self.assertTrue(
151            expr_result.IsValid(),
152            'got a valid expression result from expression "subclass.getMember()"')
153        self.assertTrue(
154            expr_result.GetValue() == "246",
155            "subclass.getMember() == 246")
156        self.assertTrue(
157            expr_result.GetType().GetName() == "int",
158            'expr_result.GetType().GetName() == "int"')
159