xref: /llvm-project/lldb/test/API/lang/cpp/template/TestTemplateArgs.py (revision 80fcecb13c388ff087a27a4b0e7ca3dd8c98eaa4)
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    def prepareProcess(self):
16        self.build()
17
18        # Create a target by the debugger.
19        exe = self.getBuildArtifact("a.out")
20        target = self.dbg.CreateTarget(exe)
21        self.assertTrue(target, VALID_TARGET)
22
23        # Set breakpoints inside and outside methods that take pointers to the
24        # containing struct.
25        line = line_number("main.cpp", "// Breakpoint 1")
26        lldbutil.run_break_set_by_file_and_line(
27            self, "main.cpp", line, num_expected_locations=1, loc_exact=True
28        )
29
30        arguments = None
31        environment = None
32
33        # Now launch the process, and do not stop at entry point.
34        process = target.LaunchSimple(
35            arguments, environment, self.get_process_working_directory()
36        )
37        self.assertTrue(process, PROCESS_IS_VALID)
38
39        # Get the thread of the process
40        self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
41        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
42
43        # Get frame for current thread
44        return thread.GetSelectedFrame()
45
46    def test_integer_args(self):
47        frame = self.prepareProcess()
48
49        testpos = frame.FindVariable("testpos")
50        self.assertTrue(
51            testpos.IsValid(), 'make sure we find a local variabble named "testpos"'
52        )
53        self.assertEqual(testpos.GetType().GetName(), "TestObj<1>")
54
55        expr_result = frame.EvaluateExpression("testpos.getArg()")
56        self.assertTrue(
57            expr_result.IsValid(),
58            'got a valid expression result from expression "testpos.getArg()"',
59        )
60        self.assertEqual(expr_result.GetValue(), "1", "testpos.getArg() == 1")
61        self.assertEqual(
62            expr_result.GetType().GetName(),
63            "int",
64            'expr_result.GetType().GetName() == "int"',
65        )
66
67        testneg = frame.FindVariable("testneg")
68        self.assertTrue(
69            testneg.IsValid(), 'make sure we find a local variabble named "testneg"'
70        )
71        self.assertEqual(testneg.GetType().GetName(), "TestObj<-1>")
72
73        expr_result = frame.EvaluateExpression("testneg.getArg()")
74        self.assertTrue(
75            expr_result.IsValid(),
76            'got a valid expression result from expression "testneg.getArg()"',
77        )
78        self.assertEqual(expr_result.GetValue(), "-1", "testneg.getArg() == -1")
79        self.assertEqual(
80            expr_result.GetType().GetName(),
81            "int",
82            'expr_result.GetType().GetName() == "int"',
83        )
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(c1.IsValid(), 'make sure we find a local variabble named "c1"')
91        self.assertEqual(c1.GetType().GetName(), "C<float, T1>")
92        f1 = (
93            c1.GetChildMemberWithName("V")
94            .GetChildAtIndex(0)
95            .GetChildMemberWithName("f")
96        )
97        self.assertEqual(f1.GetType().GetName(), "float")
98        self.assertEqual(f1.GetValue(), "1.5")
99
100        c2 = frame.FindVariable("c2")
101        self.assertTrue(c2.IsValid(), 'make sure we find a local variabble named "c2"')
102        self.assertEqual(c2.GetType().GetName(), "C<double, T1, T2>")
103        f2 = (
104            c2.GetChildMemberWithName("V")
105            .GetChildAtIndex(0)
106            .GetChildMemberWithName("f")
107        )
108        self.assertEqual(f2.GetType().GetName(), "double")
109        self.assertEqual(f2.GetValue(), "1.5")
110        f3 = (
111            c2.GetChildMemberWithName("V")
112            .GetChildAtIndex(1)
113            .GetChildMemberWithName("f")
114        )
115        self.assertEqual(f3.GetType().GetName(), "double")
116        self.assertEqual(f3.GetValue(), "2.5")
117        f4 = (
118            c2.GetChildMemberWithName("V")
119            .GetChildAtIndex(1)
120            .GetChildMemberWithName("i")
121        )
122        self.assertEqual(f4.GetType().GetName(), "int")
123        self.assertEqual(f4.GetValue(), "42")
124
125    # Gcc does not generate the necessary DWARF attribute for enum template
126    # parameters.
127    @expectedFailureAll(bugnumber="llvm.org/pr28354", compiler="gcc")
128    @skipIf(dwarf_version=["<", "4"])
129    def test_enum_args(self):
130        frame = self.prepareProcess()
131
132        # Make sure "member" can be displayed and also used in an expression
133        # correctly
134        member = frame.FindVariable("member")
135        self.assertTrue(
136            member.IsValid(), 'make sure we find a local variabble named "member"'
137        )
138        self.assertEqual(member.GetType().GetName(), "EnumTemplate<EnumType::Member>")
139
140        expr_result = frame.EvaluateExpression("member.getMember()")
141        self.assertTrue(
142            expr_result.IsValid(),
143            'got a valid expression result from expression "member.getMember()"',
144        )
145        self.assertEqual(expr_result.GetValue(), "123", "member.getMember() == 123")
146        self.assertEqual(
147            expr_result.GetType().GetName(),
148            "int",
149            'expr_result.GetType().GetName() == "int"',
150        )
151
152        # Make sure "subclass" can be displayed and also used in an expression
153        # correctly
154        subclass = frame.FindVariable("subclass")
155        self.assertTrue(
156            subclass.IsValid(), 'make sure we find a local variabble named "subclass"'
157        )
158        self.assertEqual(
159            subclass.GetType().GetName(), "EnumTemplate<EnumType::Subclass>"
160        )
161
162        expr_result = frame.EvaluateExpression("subclass.getMember()")
163        self.assertTrue(
164            expr_result.IsValid(),
165            'got a valid expression result from expression "subclass.getMember()"',
166        )
167        self.assertEqual(expr_result.GetValue(), "246", "subclass.getMember() == 246")
168        self.assertEqual(
169            expr_result.GetType().GetName(),
170            "int",
171            'expr_result.GetType().GetName() == "int"',
172        )
173