Michael137 created this revision.
Michael137 added reviewers: aprantl, martong.
Herald added a subscriber: rnkovacs.
Herald added a project: All.
Michael137 requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

The problem here is that the ASTImporter adds
the template base class member FieldDecl to
the DeclContext twice. This happens because
we don't construct a `LookupPtr` for decls
that originate from modules and thus the
ASTImporter never realizes that the FieldDecl
has already been imported. These duplicate
decls then break the assumption of the LayoutBuilder
which expects only a single member decl to
exist.

The test will be fixed by a follow-up revision
and is thus skipped for now.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133944

Files:
  lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/Makefile
  
lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/TestBaseTemplateWithSameArg.py
  lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/base_module.cpp
  lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/base_module.h
  lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/main.cpp
  lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module.modulemap
  lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module1.cpp
  lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module1.h
  lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module2.cpp
  lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module2.h

Index: lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module2.h
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module2.h
@@ -0,0 +1,10 @@
+#ifndef MOD2_H_IN
+#define MOD2_H_IN
+
+#include "base_module.h"
+
+struct ClassInMod2 {
+  ClassInMod3<int> VecInMod2;
+};
+
+#endif
Index: lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module2.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module2.cpp
@@ -0,0 +1,3 @@
+#include "module2.h"
+
+namespace crash {} // namespace crash
Index: lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module1.h
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module1.h
@@ -0,0 +1,10 @@
+#ifndef MOD1_H_IN
+#define MOD1_H_IN
+
+#include "base_module.h"
+
+struct ClassInMod1 {
+  ClassInMod3<float> VecInMod1;
+};
+
+#endif // _H_IN
Index: lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module1.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module1.cpp
@@ -0,0 +1,3 @@
+#include "module1.h"
+
+namespace crash {} // namespace crash
Index: lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module.modulemap
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/module.modulemap
@@ -0,0 +1,14 @@
+module Module1 {
+  header "module1.h"
+  export *
+}
+
+module Module2 {
+  header "module2.h"
+  export *
+}
+
+module BaseModule {
+  header "base_module.h"
+  export *
+}
Index: lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/main.cpp
@@ -0,0 +1,15 @@
+#include "module1.h"
+#include "module2.h"
+
+#include <cstdio>
+
+int main() {
+  ClassInMod1 FromMod1;
+  ClassInMod2 FromMod2;
+
+  FromMod1.VecInMod1.BaseMember = 137;
+  FromMod2.VecInMod2.BaseMember = 42;
+
+  std::puts("Break here");
+  return 0;
+}
Index: lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/base_module.h
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/base_module.h
@@ -0,0 +1,8 @@
+#ifndef MOD3_H_IN
+#define MOD3_H_IN
+
+template <typename SIZE_T> struct ClassInMod3Base { int BaseMember = 0; };
+
+template <typename T> struct ClassInMod3 : public ClassInMod3Base<int> {};
+
+#endif // _H_IN
Index: lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/base_module.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/base_module.cpp
@@ -0,0 +1,3 @@
+#include "base_module.h"
+
+namespace crash {} // namespace crash
Index: lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/TestBaseTemplateWithSameArg.py
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/TestBaseTemplateWithSameArg.py
@@ -0,0 +1,56 @@
+"""
+Tests the scenario where we evaluate expressions
+of two types in different modules that reference
+a base class template instantiated with the same
+template argument.
+
+Note that,
+1. Since the decls originate from modules, LLDB
+   marks them as such and Clang doesn't create
+   a LookupPtr map on the corresponding DeclContext.
+   This prevents regular DeclContext::lookup from
+   succeeding.
+2. Because we reference the same base template
+   from two different modules we get a redeclaration
+   chain for the base class's ClassTemplateSpecializationDecl.
+   The importer will import all FieldDecls into the
+   same DeclContext on the redeclaration chain. If
+   we don't do the bookkeeping correctly we end up
+   with duplicate decls on the same DeclContext leading
+   to crashes down the line.
+"""
+
+import lldb
+import os
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestBaseTemplateWithSameArg(TestBase):
+
+    @add_test_categories(["gmodules"])
+    @skipIf(bugnumber='rdar://96581048')
+    def test_same_base_template_arg(self):
+        self.build()
+
+        self.main_source_file = lldb.SBFileSpec("main.cpp")
+
+        (target, process, main_thread, _) = lldbutil.run_to_source_breakpoint(self,
+                                                "Break here", self.main_source_file)
+
+        self.expect_expr("FromMod1", result_type="ClassInMod1", result_children=[
+                ValueCheck(name="VecInMod1", children=[
+                        ValueCheck(name="ClassInMod3Base<int>", children=[
+                            ValueCheck(name="BaseMember", value="137")
+                        ])
+                    ])
+            ])
+
+        self.expect_expr("FromMod2", result_type="ClassInMod2", result_children=[
+                ValueCheck(name="VecInMod2", children=[
+                        ValueCheck(name="ClassInMod3Base<int>", children=[
+                            ValueCheck(name="BaseMember", value="42")
+                        ])
+                    ])
+            ])
Index: lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/lang/cpp/gmodules/base-template-with-same-arg/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES   := main.cpp module1.cpp module2.cpp base_module.cpp
+
+include Makefile.rules
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to