xref: /llvm-project/lldb/test/API/lang/cpp/gmodules/template-with-same-arg/TestTemplateWithSameArg.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1"""
2Tests the scenario where we evaluate expressions
3of two types in different modules that reference
4a class template instantiated with the same
5template argument.
6
7Note that,
81. Since the decls originate from modules, LLDB
9   marks them as such and Clang doesn't create
10   a LookupPtr map on the corresponding DeclContext.
11   This prevents regular DeclContext::lookup from
12   succeeding.
132. Because we reference the same class template
14   from two different modules we get a redeclaration
15   chain for the class's ClassTemplateSpecializationDecl.
16   The importer will import all FieldDecls into the
17   same DeclContext on the redeclaration chain. If
18   we don't do the bookkeeping correctly we end up
19   with duplicate decls on the same DeclContext leading
20   to crashes down the line.
21"""
22
23import lldb
24from lldbsuite.test.decorators import *
25from lldbsuite.test.lldbtest import *
26from lldbsuite.test import lldbutil
27
28
29class TestTemplateWithSameArg(TestBase):
30    def setUp(self):
31        TestBase.setUp(self)
32        self.build()
33        self.main_source_file = lldb.SBFileSpec("main.cpp")
34
35    @add_test_categories(["gmodules"])
36    def test_same_template_arg(self):
37        lldbutil.run_to_source_breakpoint(self, "Break here", self.main_source_file)
38
39        self.expect_expr(
40            "FromMod1",
41            result_type="ClassInMod1",
42            result_children=[
43                ValueCheck(
44                    name="VecInMod1", children=[ValueCheck(name="Member", value="137")]
45                )
46            ],
47        )
48
49        self.expect_expr(
50            "FromMod2",
51            result_type="ClassInMod2",
52            result_children=[
53                ValueCheck(
54                    name="VecInMod2", children=[ValueCheck(name="Member", value="42")]
55                )
56            ],
57        )
58
59    @add_test_categories(["gmodules"])
60    def test_duplicate_decls(self):
61        lldbutil.run_to_source_breakpoint(self, "Break here", self.main_source_file)
62
63        self.expect_expr("(intptr_t)&FromMod1 + (intptr_t)&FromMod2")
64
65        # Make sure we only have a single 'Member' decl on the AST
66        self.filecheck("target module dump ast", __file__)
67
68
69# CHECK:      ClassTemplateSpecializationDecl {{.*}} imported in Module2 struct ClassInMod3 definition
70# CHECK-NEXT: |-DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial
71# CHECK-NEXT: | |-DefaultConstructor exists trivial needs_implicit
72# CHECK-NEXT: | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
73# CHECK-NEXT: | |-MoveConstructor exists simple trivial needs_implicit
74# CHECK-NEXT: | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
75# CHECK-NEXT: | |-MoveAssignment exists simple trivial needs_implicit
76# CHECK-NEXT: | `-Destructor simple irrelevant trivial needs_implicit
77# CHECK-NEXT: |-TemplateArgument type 'int'
78# CHECK-NEXT: | `-BuiltinType {{.*}} 'int'
79# CHECK-NEXT: `-FieldDecl {{.*}} imported in Module2 Member 'int'
80