Hi clayborg,

This is progress toward PR19676/PR20781 and should have both cases error rather 
than crashing the debugger
(The former PR already had a similar work around, but I believe the original 
test case had the same issue as PR20781, so it never fully worked). Ideally, we 
need to figure out how to search other images in the process for a definition 
of this class at this point, instead of just pretending it's empty (which is 
what this patch does), but I don't know enough about LLDB to make that happen. 
Pointers appreciated.

REPOSITORY
  rL LLVM

http://reviews.llvm.org/D10509

Files:
  source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  source/Symbol/ClangASTType.cpp
  test/types/TestForwardTypes.py
  test/types/forward_inheritance.cpp
  test/types/forward_member.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2176,7 +2176,23 @@
                                         }
                                     }
                                 }
-                                
+
+                                if (member_clang_type.GetCompleteType() == false)
+                                {
+                                    GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 "  DW_TAG_member '%s' refers to type '%s' that is a forward declaration, not a complete definition."
+                                                                               "\nThis can happen due to missing images or compiler bugs.",
+                                                                               MakeUserID(die->GetOffset()),
+                                                                               name,
+                                                                               member_clang_type.GetTypeName().GetCString());
+
+                                    // We have no choice other than to pretend that the base class
+                                    // is complete. If we don't do this, clang will crash later when computing
+                                    // the object layout.
+                                    member_clang_type.StartTagDeclarationDefinition ();
+                                    member_clang_type.CompleteTagDeclarationDefinition ();
+                                }
+
+
                                 field_decl = class_clang_type.AddFieldToRecordType (name,
                                                                                     member_clang_type,
                                                                                     accessibility,
Index: source/Symbol/ClangASTType.cpp
===================================================================
--- source/Symbol/ClangASTType.cpp
+++ source/Symbol/ClangASTType.cpp
@@ -5848,6 +5848,13 @@
     if (IsValid())
     {
         clang::QualType qual_type (GetQualType());
+        clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
+        if (cxx_record_decl)
+        {
+            cxx_record_decl->startDefinition();
+            return true;
+        }
+
         const clang::Type *t = qual_type.getTypePtr();
         if (t)
         {
Index: test/types/TestForwardTypes.py
===================================================================
--- /dev/null
+++ test/types/TestForwardTypes.py
@@ -0,0 +1,44 @@
+"""
+Test that forward declarations to types in other compilation units do not crash
+the debugger.
+"""
+
+import AbstractBase
+import unittest2
+import lldb
+import sys
+from lldbtest import *
+
+class ForwardTypesTestCase(AbstractBase.GenericTester):
+    mydir = AbstractBase.GenericTester.compute_mydir(__file__)
+
+    def setUp(self):
+        # Call super's setUp().
+        AbstractBase.GenericTester.setUp(self)
+        # disable "There is a running process, kill it and restart?" prompt
+        self.runCmd("settings set auto-confirm true")
+        self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm"))
+
+    @dwarf_test
+    def test_forward_member(self):
+        """Test that members with forwarded debug info don't crash the compiler"""
+        self.source = 'forward_member.cpp'
+        self.buildDwarf()
+        target = self.dbg.createTarget("a.out")
+        self.assertTrue(target, VALID_TARGET)
+        self.runCmd("p (bar_t*)0")
+
+    @dwarf_test
+    def test_forward_inheritance(self):
+        """Test that bases with forwarded debug info don't crash the compiler"""
+        self.source = 'forward_inheritance.cpp'
+        self.buildDwarf()
+        target = self.dbg.createTarget("a.out")
+        self.assertTrue(target, VALID_TARGET)
+        self.runCmd("p (bar*)0")
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()
Index: test/types/forward_inheritance.cpp
===================================================================
--- /dev/null
+++ test/types/forward_inheritance.cpp
@@ -0,0 +1,12 @@
+template<typename T>
+class foo {
+  void func() { }
+};
+ 
+extern template class foo<int>;
+typedef foo<int> fooint; 
+
+class bar : public fooint {
+};
+
+bar f;
Index: test/types/forward_member.cpp
===================================================================
--- /dev/null
+++ test/types/forward_member.cpp
@@ -0,0 +1,13 @@
+template<typename T>
+struct foo {
+  void func() { }
+};
+ 
+extern template struct foo<int>;
+typedef foo<int> fooint; 
+
+typedef struct bar {
+    fooint foo;
+} bar_t;
+
+bar_t f;
_______________________________________________
lldb-commits mailing list
lldb-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to