[Lldb-commits] [lldb] b3b9528 - [lldb/DWARF] Look for complete member definitions in other modules

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Fri Jul 3 07:54:26 PDT 2020


Author: Pavel Labath
Date: 2020-07-03T16:50:49+02:00
New Revision: b3b952873f3705e6877644013461be7923c6caad

URL: https://github.com/llvm/llvm-project/commit/b3b952873f3705e6877644013461be7923c6caad
DIFF: https://github.com/llvm/llvm-project/commit/b3b952873f3705e6877644013461be7923c6caad.diff

LOG: [lldb/DWARF] Look for complete member definitions in other modules

With -flimit-debug-info, we can have a definition of a class, but no
definition for some of its members. This extends the same logic we were
using for incomplete base classes to cover incomplete members too.

Test forward-declarations.s is removed as it is no longer applicable --
we don't warn anymore when encountering incomplete members as they could
be completed elsewhere. New checks added to TestLimitDebugInfo cover the
handling of incomplete members more thoroughly.

Added: 
    

Modified: 
    lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
    lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
    lldb/test/API/functionalities/limit-debug-info/main.cpp
    lldb/test/API/functionalities/limit-debug-info/one.cpp
    lldb/test/API/functionalities/limit-debug-info/onetwo.h
    lldb/test/API/functionalities/limit-debug-info/two.cpp

Removed: 
    lldb/test/Shell/SymbolFile/DWARF/forward-declarations.s


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 4bf5796ed59d..0bb69eb91362 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2741,31 +2741,21 @@ void DWARFASTParserClang::ParseSingleMember(
 
           if (TypeSystemClang::IsCXXClassType(member_clang_type) &&
               !member_clang_type.GetCompleteType()) {
-            if (die.GetCU()->GetProducer() == eProducerClang)
-              module_sp->ReportError(
-                  "DWARF DIE at 0x%8.8x (class %s) has a member variable "
-                  "0x%8.8x (%s) whose type is a forward declaration, not a "
-                  "complete definition.\nTry compiling the source file "
-                  "with -fstandalone-debug",
-                  parent_die.GetOffset(), parent_die.GetName(), die.GetOffset(),
-                  name);
-            else
-              module_sp->ReportError(
-                  "DWARF DIE at 0x%8.8x (class %s) has a member variable "
-                  "0x%8.8x (%s) whose type is a forward declaration, not a "
-                  "complete definition.\nPlease file a bug against the "
-                  "compiler and include the preprocessed output for %s",
-                  parent_die.GetOffset(), parent_die.GetName(), die.GetOffset(),
-                  name, GetUnitName(parent_die).c_str());
-            // We have no choice other than to pretend that the member
-            // class is complete. If we don't do this, clang will crash
-            // when trying to layout the class. Since we provide layout
-            // assistance, all ivars in this class and other classes will
-            // be fine, this is the best we can do short of crashing.
+            // Mark the class as complete, ut we make a note of the fact that
+            // this class is not _really_ complete so we can later search for a
+            // definition in a 
diff erent module.
+            // Since we provide layout assistance, all ivars in this class and
+            // other classes will be fine even if we are not able to find the
+            // definition elsewhere.
             if (TypeSystemClang::StartTagDeclarationDefinition(
                     member_clang_type)) {
               TypeSystemClang::CompleteTagDeclarationDefinition(
                   member_clang_type);
+              const auto *td = TypeSystemClang::GetQualType(
+                                   member_clang_type.GetOpaqueQualType())
+                                   .getTypePtr()
+                                   ->getAsTagDecl();
+              m_ast.GetMetadata(td)->SetIsForcefullyCompleted();
             } else {
               module_sp->ReportError(
                   "DWARF DIE at 0x%8.8x (class %s) has a member variable "

diff  --git a/lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py b/lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
index d22aeaace7bf..396861f5eb76 100644
--- a/lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
+++ b/lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
@@ -44,11 +44,16 @@ def test_one_and_two_debug(self):
         # all members.
         self.expect_expr("inherits_from_one.member", result_value="47")
         self.expect_expr("inherits_from_one.one", result_value="142")
-
         self.expect_expr("inherits_from_two.member", result_value="47")
         self.expect_expr("inherits_from_two.one", result_value="142")
         self.expect_expr("inherits_from_two.two", result_value="242")
 
+        self.expect_expr("one_as_member.member", result_value="47")
+        self.expect_expr("one_as_member.one.member", result_value="147")
+        self.expect_expr("two_as_member.member", result_value="47")
+        self.expect_expr("two_as_member.two.one.member", result_value="147")
+        self.expect_expr("two_as_member.two.member", result_value="247")
+
     @skipIf(bugnumber="pr46284", debug_info="gmodules")
     @skipIfWindows # Clang emits type info even with -flimit-debug-info
     def test_two_debug(self):
@@ -63,12 +68,19 @@ def test_two_debug(self):
         self.expect_expr("inherits_from_one.member", result_value="47")
         self.expect("expr inherits_from_one.one", error=True,
             substrs=["no member named 'one' in 'InheritsFromOne'"])
-
         self.expect_expr("inherits_from_two.member", result_value="47")
         self.expect("expr inherits_from_two.one", error=True,
             substrs=["no member named 'one' in 'InheritsFromTwo'"])
         self.expect_expr("inherits_from_two.two", result_value="242")
 
+        self.expect_expr("one_as_member.member", result_value="47")
+        self.expect("expr one_as_member.one.member", error=True,
+                substrs=["no member named 'member' in 'member::One'"])
+        self.expect_expr("two_as_member.member", result_value="47")
+        self.expect("expr two_as_member.two.one.member", error=True,
+                substrs=["no member named 'member' in 'member::One'"])
+        self.expect_expr("two_as_member.two.member", result_value="247")
+
     @skipIf(bugnumber="pr46284", debug_info="gmodules")
     @skipIfWindows # Clang emits type info even with -flimit-debug-info
     def test_one_debug(self):
@@ -85,9 +97,16 @@ def test_one_debug(self):
         # "One".
         self.expect_expr("inherits_from_one.member", result_value="47")
         self.expect_expr("inherits_from_one.one", result_value="142")
-
         self.expect_expr("inherits_from_two.member", result_value="47")
         self.expect("expr inherits_from_two.one", error=True,
             substrs=["no member named 'one' in 'InheritsFromTwo'"])
         self.expect("expr inherits_from_two.two", error=True,
             substrs=["no member named 'two' in 'InheritsFromTwo'"])
+
+        self.expect_expr("one_as_member.member", result_value="47")
+        self.expect_expr("one_as_member.one.member", result_value="147")
+        self.expect_expr("two_as_member.member", result_value="47")
+        self.expect("expr two_as_member.two.one.member", error=True,
+                substrs=["no member named 'one' in 'member::Two'"])
+        self.expect("expr two_as_member.two.member", error=True,
+                substrs=["no member named 'member' in 'member::Two'"])

diff  --git a/lldb/test/API/functionalities/limit-debug-info/main.cpp b/lldb/test/API/functionalities/limit-debug-info/main.cpp
index e3049ed74489..886b3feec434 100644
--- a/lldb/test/API/functionalities/limit-debug-info/main.cpp
+++ b/lldb/test/API/functionalities/limit-debug-info/main.cpp
@@ -10,4 +10,16 @@ struct InheritsFromTwo : Two {
   int member = 47;
 } inherits_from_two;
 
+struct OneAsMember {
+  constexpr OneAsMember() = default;
+  member::One one;
+  int member = 47;
+} one_as_member;
+
+struct TwoAsMember {
+  constexpr TwoAsMember() = default;
+  member::Two two;
+  int member = 47;
+} two_as_member;
+
 int main() { return 0; }

diff  --git a/lldb/test/API/functionalities/limit-debug-info/one.cpp b/lldb/test/API/functionalities/limit-debug-info/one.cpp
index 728875dd9e55..ee275e3321e4 100644
--- a/lldb/test/API/functionalities/limit-debug-info/one.cpp
+++ b/lldb/test/API/functionalities/limit-debug-info/one.cpp
@@ -1,3 +1,4 @@
 #include "onetwo.h"
 
 One::~One() = default;
+member::One::~One() = default;

diff  --git a/lldb/test/API/functionalities/limit-debug-info/onetwo.h b/lldb/test/API/functionalities/limit-debug-info/onetwo.h
index 82df76c64b58..6822d84803fe 100644
--- a/lldb/test/API/functionalities/limit-debug-info/onetwo.h
+++ b/lldb/test/API/functionalities/limit-debug-info/onetwo.h
@@ -9,3 +9,18 @@ struct Two : One {
   constexpr Two() = default;
   ~Two() override;
 };
+
+namespace member {
+struct One {
+  int member = 147;
+  constexpr One() = default;
+  virtual ~One();
+};
+
+struct Two {
+  One one;
+  int member = 247;
+  constexpr Two() = default;
+  virtual ~Two();
+};
+} // namespace member

diff  --git a/lldb/test/API/functionalities/limit-debug-info/two.cpp b/lldb/test/API/functionalities/limit-debug-info/two.cpp
index 928b091728c3..db98c5e8d3dc 100644
--- a/lldb/test/API/functionalities/limit-debug-info/two.cpp
+++ b/lldb/test/API/functionalities/limit-debug-info/two.cpp
@@ -1,3 +1,4 @@
 #include "onetwo.h"
 
 Two::~Two() = default;
+member::Two::~Two() = default;

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/forward-declarations.s b/lldb/test/Shell/SymbolFile/DWARF/forward-declarations.s
deleted file mode 100644
index 952c4ee7f87e..000000000000
--- a/lldb/test/Shell/SymbolFile/DWARF/forward-declarations.s
+++ /dev/null
@@ -1,111 +0,0 @@
-# Test handling of the situation (including the error message) where a structure
-# has a incomplete member.
-
-# REQUIRES: x86
-
-# RUN: llvm-mc -triple x86_64-pc-linux -filetype=obj %s -o %t
-# RUN: %lldb %t -o "target var b" -b 2>&1 | FileCheck %s
-
-# CHECK: error: {{.*}} DWARF DIE at 0x0000002b (class B) has a member variable 0x00000030 (a) whose type is a forward declaration, not a complete definition.
-# CHECK-NEXT: Please file a bug against the compiler and include the preprocessed output for /tmp/a.cc
-
-# CHECK: b = (a = A @ 0x0000000000000001)
-
-        .type   b, at object               # @b
-        .comm   b,1,1
-        .section        .debug_str,"MS", at progbits,1
-.Linfo_string0:
-        .asciz  "Hand-written DWARF"
-.Lcu_name:
-        .asciz  "/tmp/a.cc"
-.Lcu_compdir:
-        .asciz  "/foo/bar"
-.Lb:
-        .asciz  "b"
-.La:
-        .asciz  "a"
-.LA:
-        .asciz  "A"
-.LB:
-        .asciz  "B"
-
-        .section        .debug_abbrev,"", at progbits
-        .byte   1                       # Abbreviation Code
-        .byte   17                      # DW_TAG_compile_unit
-        .byte   1                       # DW_CHILDREN_yes
-        .byte   37                      # DW_AT_producer
-        .byte   14                      # DW_FORM_strp
-        .byte   3                       # DW_AT_name
-        .byte   14                      # DW_FORM_strp
-        .byte   27                      # DW_AT_comp_dir
-        .byte   14                      # DW_FORM_strp
-        .byte   0                       # EOM(1)
-        .byte   0                       # EOM(2)
-        .byte   2                       # Abbreviation Code
-        .byte   52                      # DW_TAG_variable
-        .byte   0                       # DW_CHILDREN_no
-        .byte   3                       # DW_AT_name
-        .byte   14                      # DW_FORM_strp
-        .byte   73                      # DW_AT_type
-        .byte   19                      # DW_FORM_ref4
-        .byte   2                       # DW_AT_location
-        .byte   24                      # DW_FORM_exprloc
-        .byte   0                       # EOM(1)
-        .byte   0                       # EOM(2)
-        .byte   3                       # Abbreviation Code
-        .byte   19                      # DW_TAG_structure_type
-        .byte   1                       # DW_CHILDREN_yes
-        .byte   3                       # DW_AT_name
-        .byte   14                      # DW_FORM_strp
-        .byte   0                       # EOM(1)
-        .byte   0                       # EOM(2)
-        .byte   4                       # Abbreviation Code
-        .byte   13                      # DW_TAG_member
-        .byte   0                       # DW_CHILDREN_no
-        .byte   3                       # DW_AT_name
-        .byte   14                      # DW_FORM_strp
-        .byte   73                      # DW_AT_type
-        .byte   19                      # DW_FORM_ref4
-        .byte   0                       # EOM(1)
-        .byte   0                       # EOM(2)
-        .byte   5                       # Abbreviation Code
-        .byte   19                      # DW_TAG_structure_type
-        .byte   0                       # DW_CHILDREN_no
-        .byte   60                      # DW_AT_declaration
-        .byte   25                      # DW_FORM_flag_present
-        .byte   3                       # DW_AT_name
-        .byte   14                      # DW_FORM_strp
-        .byte   0                       # EOM(1)
-        .byte   0                       # EOM(2)
-        .byte   0                       # EOM(3)
-
-        .section        .debug_info,"", at progbits
-.Lcu_begin0:
-        .long   .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
-.Ldebug_info_start0:
-        .short  4                       # DWARF version number
-        .long   .debug_abbrev           # Offset Into Abbrev. Section
-        .byte   8                       # Address Size (in bytes)
-        .byte   1                       # Abbrev [1] 0xb:0x46 DW_TAG_compile_unit
-        .long   .Linfo_string0          # DW_AT_producer
-        .long   .Lcu_name               # DW_AT_name
-        .long   .Lcu_compdir            # DW_AT_comp_dir
-        .byte   2                       # Abbrev [2] 0x1e:0x15 DW_TAG_variable
-        .long   .Lb                     # DW_AT_name
-        .long   .LB_die-.Lcu_begin0     # DW_AT_type
-        .byte   9                       # DW_AT_location
-        .byte   3
-        .quad   b
-.LB_die:
-        .byte   3                       # Abbrev [3] 0x33:0x15 DW_TAG_structure_type
-        .long   .LB                     # DW_AT_name
-        .byte   4                       # Abbrev [4] 0x3b:0xc DW_TAG_member
-        .long   .La                     # DW_AT_name
-        .long   .LA_die-.Lcu_begin0     # DW_AT_type
-        .byte   0                       # End Of Children Mark
-.LA_die:
-        .byte   5                       # Abbrev [5] 0x48:0x8 DW_TAG_structure_type
-                                        # DW_AT_declaration
-        .long   .LA                     # DW_AT_name
-        .byte   0                       # End Of Children Mark
-.Ldebug_info_end0:


        


More information about the lldb-commits mailing list