[lldb] Forcefully complete a type when adding typedefs
authorPavel Labath <pavel@labath.sk>
Wed, 19 Aug 2020 13:52:58 +0000 (15:52 +0200)
committerPavel Labath <pavel@labath.sk>
Thu, 20 Aug 2020 13:19:10 +0000 (15:19 +0200)
This is very similar to D85968, only more elusive to since we were not
adding the typedef type to the relevant DeclContext until D86140, which
meant that the DeclContext was populated (and the relevant assertion
hit) only after importing the type into the expression ast in a
particular way.

I haven't checked whether this situation can be hit in the gmodules
case, but my money is on "yes".

Differential Revision: https://reviews.llvm.org/D86216

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
lldb/test/Shell/SymbolFile/DWARF/DW_AT_declaration-with-children.s

index 486945c..2fee87d 100644 (file)
@@ -556,42 +556,51 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
   TypeSP type_sp;
   CompilerType clang_type;
 
-  if (tag == DW_TAG_typedef && attrs.type.IsValid()) {
-    // Try to parse a typedef from the (DWARF embedded in the) Clang
-    // module file first as modules can contain typedef'ed
-    // structures that have no names like:
-    //
-    //  typedef struct { int a; } Foo;
-    //
-    // In this case we will have a structure with no name and a
-    // typedef named "Foo" that points to this unnamed
-    // structure. The name in the typedef is the only identifier for
-    // the struct, so always try to get typedefs from Clang modules
-    // if possible.
-    //
-    // The type_sp returned will be empty if the typedef doesn't
-    // exist in a module file, so it is cheap to call this function
-    // just to check.
-    //
-    // If we don't do this we end up creating a TypeSP that says
-    // this is a typedef to type 0x123 (the DW_AT_type value would
-    // be 0x123 in the DW_TAG_typedef), and this is the unnamed
-    // structure type. We will have a hard time tracking down an
-    // unnammed structure type in the module debug info, so we make
-    // sure we don't get into this situation by always resolving
-    // typedefs from the module.
-    const DWARFDIE encoding_die = attrs.type.Reference();
-
-    // First make sure that the die that this is typedef'ed to _is_
-    // just a declaration (DW_AT_declaration == 1), not a full
-    // definition since template types can't be represented in
-    // modules since only concrete instances of templates are ever
-    // emitted and modules won't contain those
-    if (encoding_die &&
-        encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
-      type_sp = ParseTypeFromClangModule(sc, die, log);
-      if (type_sp)
-        return type_sp;
+  if (tag == DW_TAG_typedef) {
+    // DeclContext will be populated when the clang type is materialized in
+    // Type::ResolveCompilerType.
+    PrepareContextToReceiveMembers(
+        m_ast, GetClangASTImporter(),
+        GetClangDeclContextContainingDIE(die, nullptr), die,
+        attrs.name.GetCString());
+
+    if (attrs.type.IsValid()) {
+      // Try to parse a typedef from the (DWARF embedded in the) Clang
+      // module file first as modules can contain typedef'ed
+      // structures that have no names like:
+      //
+      //  typedef struct { int a; } Foo;
+      //
+      // In this case we will have a structure with no name and a
+      // typedef named "Foo" that points to this unnamed
+      // structure. The name in the typedef is the only identifier for
+      // the struct, so always try to get typedefs from Clang modules
+      // if possible.
+      //
+      // The type_sp returned will be empty if the typedef doesn't
+      // exist in a module file, so it is cheap to call this function
+      // just to check.
+      //
+      // If we don't do this we end up creating a TypeSP that says
+      // this is a typedef to type 0x123 (the DW_AT_type value would
+      // be 0x123 in the DW_TAG_typedef), and this is the unnamed
+      // structure type. We will have a hard time tracking down an
+      // unnammed structure type in the module debug info, so we make
+      // sure we don't get into this situation by always resolving
+      // typedefs from the module.
+      const DWARFDIE encoding_die = attrs.type.Reference();
+
+      // First make sure that the die that this is typedef'ed to _is_
+      // just a declaration (DW_AT_declaration == 1), not a full
+      // definition since template types can't be represented in
+      // modules since only concrete instances of templates are ever
+      // emitted and modules won't contain those
+      if (encoding_die &&
+          encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
+        type_sp = ParseTypeFromClangModule(sc, die, log);
+        if (type_sp)
+          return type_sp;
+      }
     }
   }
 
index f179029..9365dd9 100644 (file)
@@ -28,6 +28,13 @@ expr b1
 # CHECK-LABEL: expr b1
 # CHECK: (B::B1) $0 = (ptr = 0x00000000baadf00d)
 
+target var c1
+# CHECK-LABEL: target var c1
+# CHECK: (C::C1) c1 = 424742
+
+expr c1
+# CHECK-LABEL: expr c1
+# CHECK: (C::C1) $1 = 424742
 #--- asm
         .text
 _ZN1AC2Ev:
@@ -42,6 +49,8 @@ a:
 
 b1:
         .quad   0xbaadf00d
+c1:
+        .long   42474247
 
         .section        .debug_abbrev,"",@progbits
         .byte   1                               # Abbreviation Code
@@ -118,6 +127,17 @@ b1:
         .byte   19                              # DW_FORM_ref4
         .byte   0                               # EOM(1)
         .byte   0                               # EOM(2)
+        .byte   9                               # Abbreviation Code
+        .byte   36                              # DW_TAG_base_type
+        .byte   0                               # DW_CHILDREN_no
+        .byte   3                               # DW_AT_name
+        .byte   8                               # DW_FORM_string
+        .byte   62                              # DW_AT_encoding
+        .byte   11                              # DW_FORM_data1
+        .byte   11                              # DW_AT_byte_size
+        .byte   11                              # DW_FORM_data1
+        .byte   0                               # EOM(1)
+        .byte   0                               # EOM(2)
         .byte   10                              # Abbreviation Code
         .byte   46                              # DW_TAG_subprogram
         .byte   1                               # DW_CHILDREN_yes
@@ -146,6 +166,15 @@ b1:
         .byte   25                              # DW_FORM_flag_present
         .byte   0                               # EOM(1)
         .byte   0                               # EOM(2)
+        .byte   12                              # Abbreviation Code
+        .byte   22                              # DW_TAG_typedef
+        .byte   0                               # DW_CHILDREN_no
+        .byte   73                              # DW_AT_type
+        .byte   19                              # DW_FORM_ref4
+        .byte   3                               # DW_AT_name
+        .byte   8                               # DW_FORM_string
+        .byte   0                               # EOM(1)
+        .byte   0                               # EOM(2)
         .byte   0                               # EOM(3)
         .section        .debug_info,"",@progbits
 .Lcu_begin0:
@@ -222,7 +251,6 @@ b1:
 .LB1:
         .byte   6                               # Abbrev [6] DW_TAG_class_type
         .asciz  "B1"                            # DW_AT_name
-                                                # DW_AT_declaration
         .byte   7                               # Abbrev [5] 0x58:0xc DW_TAG_member
         .asciz  "ptr"                           # DW_AT_name
         .long   .LAptr                          # DW_AT_type
@@ -237,5 +265,33 @@ b1:
         .byte   3
         .quad   b1
 
+# Case 3: A typedef in DW_AT_declaration struct.
+# C++ equivalent:
+# struct C {
+#   virtual ~C(); // not defined here
+#   typedef int C1;
+# };
+# C::C1 c1;
+.Lint:
+        .byte   9                               # Abbrev [9] DW_TAG_base_type
+        .asciz  "int"                           # DW_AT_name
+        .byte   5                               # DW_AT_encoding
+        .byte   4                               # DW_AT_byte_size
+        .byte   3                               # Abbrev [3] DW_TAG_structure_type
+        .asciz  "C"                             # DW_AT_name
+                                                # DW_AT_declaration
+.LC1:
+        .byte   12                              # Abbrev [12] DW_TAG_typedef
+        .long   .Lint-.Lcu_begin0               # DW_AT_type
+        .asciz  "C1"                            # DW_AT_name
+        .byte   0                               # End Of Children Mark
+
+        .byte   2                               # Abbrev [2] DW_TAG_variable
+        .asciz  "c1"                            # DW_AT_name
+        .long   .LC1-.Lcu_begin0                # DW_AT_type
+        .byte   9                               # DW_AT_location
+        .byte   3
+        .quad   c1
+
         .byte   0                               # End Of Children Mark
 .Ldebug_info_end0: