[Lldb-commits] [lldb] [lldb][DWARF] Delay struct/class/union definition DIE searching when parsing declaration DIEs. (PR #90663)

Zequan Wu via lldb-commits lldb-commits at lists.llvm.org
Tue May 7 14:01:02 PDT 2024


https://github.com/ZequanWu updated https://github.com/llvm/llvm-project/pull/90663

>From 4e800003099b593e66f12dc21be5fbac5279e03e Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Tue, 30 Apr 2024 16:23:11 -0400
Subject: [PATCH 1/8] [lldb][DWARF] Delay struct/class/union definition DIE
 searching when parsing declaration DIEs.

---
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  | 270 +++++++-----------
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      | 105 ++++++-
 .../SymbolFile/DWARF/SymbolFileDWARF.h        |  14 +
 .../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp   |   5 +
 .../SymbolFile/DWARF/SymbolFileDWARFDwo.h     |   2 +
 .../SymbolFile/DWARF/UniqueDWARFASTType.cpp   |  95 +++---
 .../SymbolFile/DWARF/UniqueDWARFASTType.h     |  21 +-
 7 files changed, 296 insertions(+), 216 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index bea11e0e3840a..7ad661c9a9d49 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -252,7 +252,8 @@ static void ForcefullyCompleteType(CompilerType type) {
 static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
                                            ClangASTImporter &ast_importer,
                                            clang::DeclContext *decl_ctx,
-                                           DWARFDIE die,
+                                           const DWARFDIE &decl_ctx_die,
+                                           const DWARFDIE &die,
                                            const char *type_name_cstr) {
   auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);
   if (!tag_decl_ctx)
@@ -279,6 +280,13 @@ static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
         type_name_cstr ? type_name_cstr : "", die.GetOffset());
   }
 
+  // By searching for the definition DIE of the decl_ctx type, we will either:
+  // 1. Found the the definition DIE and start its definition with
+  // TypeSystemClang::StartTagDeclarationDefinition.
+  // 2. Unable to find it, then need to forcefully complete it.
+  die.GetDWARF()->FindDefinitionDIE(decl_ctx_die);
+  if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined())
+    return;
   // We don't have a type definition and/or the import failed. We must
   // forcefully complete the type to avoid crashes.
   ForcefullyCompleteType(type);
@@ -620,10 +628,11 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
   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());
+    DWARFDIE decl_ctx_die;
+    clang::DeclContext *decl_ctx =
+        GetClangDeclContextContainingDIE(die, &decl_ctx_die);
+    PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx,
+                                   decl_ctx_die, die, attrs.name.GetCString());
 
     if (attrs.type.IsValid()) {
       // Try to parse a typedef from the (DWARF embedded in the) Clang
@@ -1100,32 +1109,6 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
         // struct and see if this is actually a C++ method
         Type *class_type = dwarf->ResolveType(decl_ctx_die);
         if (class_type) {
-          if (class_type->GetID() != decl_ctx_die.GetID() ||
-              IsClangModuleFwdDecl(decl_ctx_die)) {
-
-            // We uniqued the parent class of this function to another
-            // class so we now need to associate all dies under
-            // "decl_ctx_die" to DIEs in the DIE for "class_type"...
-            DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID());
-
-            if (class_type_die) {
-              std::vector<DWARFDIE> failures;
-
-              CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die,
-                                         class_type, failures);
-
-              // FIXME do something with these failures that's
-              // smarter than just dropping them on the ground.
-              // Unfortunately classes don't like having stuff added
-              // to them after their definitions are complete...
-
-              Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
-              if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
-                return type_ptr->shared_from_this();
-              }
-            }
-          }
-
           if (attrs.specification.IsValid()) {
             // We have a specification which we are going to base our
             // function prototype off of, so we need this type to be
@@ -1260,6 +1243,39 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
               }
             }
           }
+          // By here, we should have already completed the c++ class_type
+          // because if either specification or abstract_origin is present, we
+          // call GetClangDeclContextForDIE to resolve the DW_TAG_subprogram
+          // refered by this one until we reached the DW_TAG_subprogram without
+          // specification or abstract_origin (the else branch above). Then the
+          // above GetFullCompilerType() will complete the class_type if it's
+          // not completed yet. After that, we will have the mapping from DIEs
+          // in class_type_die to DeclContexts in m_die_to_decl_ctx.
+          if (class_type->GetID() != decl_ctx_die.GetID() ||
+              IsClangModuleFwdDecl(decl_ctx_die)) {
+
+            // We uniqued the parent class of this function to another
+            // class so we now need to associate all dies under
+            // "decl_ctx_die" to DIEs in the DIE for "class_type"...
+            DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID());
+
+            if (class_type_die) {
+              std::vector<DWARFDIE> failures;
+
+              CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die,
+                                         class_type, failures);
+
+              // FIXME do something with these failures that's
+              // smarter than just dropping them on the ground.
+              // Unfortunately classes don't like having stuff added
+              // to them after their definitions are complete...
+
+              Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
+              if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
+                return type_ptr->shared_from_this();
+              }
+            }
+          }
         }
       }
     }
@@ -1651,6 +1667,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
 
   ConstString unique_typename(attrs.name);
   Declaration unique_decl(attrs.decl);
+  uint64_t byte_size = attrs.byte_size.value_or(0);
 
   if (attrs.name) {
     if (Language::LanguageIsCPlusPlus(cu_language)) {
@@ -1664,13 +1681,34 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
     }
 
     if (dwarf->GetUniqueDWARFASTTypeMap().Find(
-            unique_typename, die, unique_decl, attrs.byte_size.value_or(-1),
-            *unique_ast_entry_up)) {
+            unique_typename, die, unique_decl, byte_size,
+            attrs.is_forward_declaration, *unique_ast_entry_up)) {
       type_sp = unique_ast_entry_up->m_type_sp;
       if (type_sp) {
         dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
         LinkDeclContextToDIE(
             GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die);
+        if (!attrs.is_forward_declaration) {
+          dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace(
+              unique_ast_entry_up->m_die.GetDIE(), *die.GetDIERef());
+          // If the parameter DIE is definition and the entry in the map is
+          // declaration, then we need to update the entry to point to the
+          // definition DIE.
+          if (unique_ast_entry_up->m_is_forward_declaration) {
+            unique_ast_entry_up->m_die = die;
+            unique_ast_entry_up->m_byte_size = byte_size;
+            unique_ast_entry_up->m_declaration = unique_decl;
+            unique_ast_entry_up->m_is_forward_declaration = false;
+            // Need to update Type ID to refer to the definition DIE. because
+            // it's used in ParseSubroutine to determine if we need to copy cxx
+            // method types from a declaration DIE to this definition DIE.
+            type_sp->SetID(die.GetID());
+            if (attrs.class_language != eLanguageTypeObjC &&
+                attrs.class_language != eLanguageTypeObjC_plus_plus)
+              TypeSystemClang::StartTagDeclarationDefinition(
+                  type_sp->GetForwardCompilerType());
+          }
+        }
         return type_sp;
       }
     }
@@ -1707,112 +1745,22 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
     attrs.is_forward_declaration = true;
   }
 
-  if (attrs.class_language == eLanguageTypeObjC ||
-      attrs.class_language == eLanguageTypeObjC_plus_plus) {
-    if (!attrs.is_complete_objc_class &&
-        die.Supports_DW_AT_APPLE_objc_complete_type()) {
-      // We have a valid eSymbolTypeObjCClass class symbol whose name
-      // matches the current objective C class that we are trying to find
-      // and this DIE isn't the complete definition (we checked
-      // is_complete_objc_class above and know it is false), so the real
-      // definition is in here somewhere
-      type_sp =
-          dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
-
-      if (!type_sp) {
-        SymbolFileDWARFDebugMap *debug_map_symfile =
-            dwarf->GetDebugMapSymfile();
-        if (debug_map_symfile) {
-          // We weren't able to find a full declaration in this DWARF,
-          // see if we have a declaration anywhere else...
-          type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE(
-              die, attrs.name, true);
-        }
-      }
-
-      if (type_sp) {
-        if (log) {
-          dwarf->GetObjectFile()->GetModule()->LogMessage(
-              log,
-              "SymbolFileDWARF({0:p}) - {1:x16}: {2} type "
-              "\"{3}\" is an "
-              "incomplete objc type, complete type is {4:x8}",
-              static_cast<void *>(this), die.GetOffset(),
-              DW_TAG_value_to_name(tag), attrs.name.GetCString(),
-              type_sp->GetID());
-        }
-
-        // We found a real definition for this type elsewhere so lets use
-        // it and cache the fact that we found a complete type for this
-        // die
-        dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
-        return type_sp;
-      }
-    }
-  }
-
   if (attrs.is_forward_declaration) {
-    // We have a forward declaration to a type and we need to try and
-    // find a full declaration. We look in the current type index just in
-    // case we have a forward declaration followed by an actual
-    // declarations in the DWARF. If this fails, we need to look
-    // elsewhere...
-    if (log) {
-      dwarf->GetObjectFile()->GetModule()->LogMessage(
-          log,
-          "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
-          "forward declaration, trying to find complete type",
-          static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
-          attrs.name.GetCString());
-    }
-
     // See if the type comes from a Clang module and if so, track down
     // that type.
     type_sp = ParseTypeFromClangModule(sc, die, log);
     if (type_sp)
       return type_sp;
-
-    // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die,
-    // type_name_const_str);
-    type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die);
-
-    if (!type_sp) {
-      SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
-      if (debug_map_symfile) {
-        // We weren't able to find a full declaration in this DWARF, see
-        // if we have a declaration anywhere else...
-        type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die);
-      }
-    }
-
-    if (type_sp) {
-      if (log) {
-        dwarf->GetObjectFile()->GetModule()->LogMessage(
-            log,
-            "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
-            "forward declaration, complete type is {4:x8}",
-            static_cast<void *>(this), die.GetOffset(),
-            DW_TAG_value_to_name(tag), attrs.name.GetCString(),
-            type_sp->GetID());
-      }
-
-      // We found a real definition for this type elsewhere so lets use
-      // it and cache the fact that we found a complete type for this die
-      dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
-      clang::DeclContext *defn_decl_ctx =
-          GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID()));
-      if (defn_decl_ctx)
-        LinkDeclContextToDIE(defn_decl_ctx, die);
-      return type_sp;
-    }
   }
+
   assert(tag_decl_kind != -1);
   UNUSED_IF_ASSERT_DISABLED(tag_decl_kind);
-  bool clang_type_was_created = false;
-  clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, nullptr);
+  DWARFDIE decl_ctx_die;
+  clang::DeclContext *decl_ctx =
+      GetClangDeclContextContainingDIE(die, &decl_ctx_die);
 
-  PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx, die,
-                                 attrs.name.GetCString());
+  PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx,
+                                 decl_ctx_die, die, attrs.name.GetCString());
 
   if (attrs.accessibility == eAccessNone && decl_ctx) {
     // Check the decl context that contains this class/struct/union. If
@@ -1850,20 +1798,20 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
             tag_decl_kind, template_param_infos);
     clang_type =
         m_ast.CreateClassTemplateSpecializationType(class_specialization_decl);
-    clang_type_was_created = true;
 
     m_ast.SetMetadata(class_template_decl, metadata);
     m_ast.SetMetadata(class_specialization_decl, metadata);
   }
 
-  if (!clang_type_was_created) {
-    clang_type_was_created = true;
+  if (!clang_type) {
     clang_type = m_ast.CreateRecordType(
         decl_ctx, GetOwningClangModule(die), attrs.accessibility,
         attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata,
         attrs.exports_symbols);
   }
-
+  if (!attrs.is_forward_declaration)
+    dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace(die.GetDIE(),
+                                                          *die.GetDIERef());
   // Store a forward declaration to this class type in case any
   // parameters in any class methods need it for the clang types for
   // function prototypes.
@@ -1880,7 +1828,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
   unique_ast_entry_up->m_type_sp = type_sp;
   unique_ast_entry_up->m_die = die;
   unique_ast_entry_up->m_declaration = unique_decl;
-  unique_ast_entry_up->m_byte_size = attrs.byte_size.value_or(0);
+  unique_ast_entry_up->m_byte_size = byte_size;
+  unique_ast_entry_up->m_is_forward_declaration = attrs.is_forward_declaration;
   dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename,
                                            *unique_ast_entry_up);
 
@@ -1921,38 +1870,33 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
           GetClangASTImporter().SetRecordLayout(record_decl, layout);
         }
       }
-    } else if (clang_type_was_created) {
-      // Start the definition if the class is not objective C since the
-      // underlying decls respond to isCompleteDefinition(). Objective
-      // C decls don't respond to isCompleteDefinition() so we can't
-      // start the declaration definition right away. For C++
-      // class/union/structs we want to start the definition in case the
-      // class is needed as the declaration context for a contained class
-      // or type without the need to complete that type..
-
-      if (attrs.class_language != eLanguageTypeObjC &&
-          attrs.class_language != eLanguageTypeObjC_plus_plus)
-        TypeSystemClang::StartTagDeclarationDefinition(clang_type);
-
-      // Leave this as a forward declaration until we need to know the
-      // details of the type. lldb_private::Type will automatically call
-      // the SymbolFile virtual function
-      // "SymbolFileDWARF::CompleteType(Type *)" When the definition
-      // needs to be defined.
-      assert(!dwarf->GetForwardDeclCompilerTypeToDIE().count(
-                 ClangUtil::RemoveFastQualifiers(clang_type)
-                     .GetOpaqueQualType()) &&
-             "Type already in the forward declaration map!");
-      // Can't assume m_ast.GetSymbolFile() is actually a
-      // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple
-      // binaries.
-      dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace(
-          ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(),
-          *die.GetDIERef());
-      m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
     }
+    // Start the definition if the class is not objective C since the
+    // underlying decls respond to isCompleteDefinition(). Objective
+    // C decls don't respond to isCompleteDefinition() so we can't
+    // start the declaration definition right away. For C++
+    // class/union/structs we want to start the definition in case the
+    // class is needed as the declaration context for a contained class
+    // or type without the need to complete that type..
+
+    if (attrs.class_language != eLanguageTypeObjC &&
+        attrs.class_language != eLanguageTypeObjC_plus_plus)
+      TypeSystemClang::StartTagDeclarationDefinition(clang_type);
   }
 
+  // Leave this as a forward declaration until we need to know the
+  // details of the type. lldb_private::Type will automatically call
+  // the SymbolFile virtual function
+  // "SymbolFileDWARF::CompleteType(Type *)" When the definition
+  // needs to be defined.
+  assert(!dwarf->GetForwardDeclCompilerTypeToDIE().count(
+             ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()) &&
+         "Type already in the forward declaration map!");
+  dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace(
+      ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(),
+      *die.GetDIERef());
+  m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
+
   // If we made a clang type, set the trivial abi if applicable: We only
   // do this for pass by value - which implies the Trivial ABI. There
   // isn't a way to assert that something that would normally be pass by
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 49f13d2c89e38..5a317db7e7402 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1631,13 +1631,19 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
     return true;
   }
 
-  DWARFDIE dwarf_die = GetDIE(die_it->getSecond());
+  DWARFDIE dwarf_die = FindDefinitionDIE(GetDIE(die_it->getSecond()));
   if (dwarf_die) {
     // Once we start resolving this type, remove it from the forward
     // declaration map in case anyone child members or other types require this
     // type to get resolved. The type will get resolved when all of the calls
     // to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
-    GetForwardDeclCompilerTypeToDIE().erase(die_it);
+    // Need to get a new iterator because FindDefinitionDIE might add new
+    // entries into the map and invalidate previous iterator.
+    auto die_it = GetForwardDeclCompilerTypeToDIE().find(
+        compiler_type_no_qualifiers.GetOpaqueQualType());
+    if (die_it != GetForwardDeclCompilerTypeToDIE().end()) {
+      GetForwardDeclCompilerTypeToDIE().erase(die_it);
+    }
 
     Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
 
@@ -1654,6 +1660,101 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
   return false;
 }
 
+DWARFDIE SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
+  auto def_die_it = GetDeclarationDIEToDefinitionDIE().find(die.GetDIE());
+  if (def_die_it != GetDeclarationDIEToDefinitionDIE().end())
+    return GetDIE(def_die_it->getSecond());
+
+  ParsedDWARFTypeAttributes attrs(die);
+  const dw_tag_t tag = die.Tag();
+  TypeSP type_sp;
+  Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
+  if (log) {
+    GetObjectFile()->GetModule()->LogMessage(
+        log,
+        "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+        "forward declaration DIE, trying to find definition DIE",
+        static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
+        attrs.name.GetCString());
+  }
+  // We haven't parse definition die for this type, starting to search for it.
+  // After we found the definition die, the GetDeclarationDIEToDefinitionDIE()
+  // map will have the new mapping from this declaration die to definition die.
+  if (attrs.class_language == eLanguageTypeObjC ||
+      attrs.class_language == eLanguageTypeObjC_plus_plus) {
+    if (!attrs.is_complete_objc_class &&
+        die.Supports_DW_AT_APPLE_objc_complete_type()) {
+      // We have a valid eSymbolTypeObjCClass class symbol whose name
+      // matches the current objective C class that we are trying to find
+      // and this DIE isn't the complete definition (we checked
+      // is_complete_objc_class above and know it is false), so the real
+      // definition is in here somewhere
+      type_sp =
+          FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
+
+      if (!type_sp) {
+        SymbolFileDWARFDebugMap *debug_map_symfile =
+            GetDebugMapSymfile();
+        if (debug_map_symfile) {
+          // We weren't able to find a full declaration in this DWARF,
+          // see if we have a declaration anywhere else...
+          type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE(
+              die, attrs.name, true);
+        }
+      }
+
+      if (type_sp && log) {
+        GetObjectFile()->GetModule()->LogMessage(
+            log,
+            "SymbolFileDWARF({0:p}) - {1:x16}: {2} type "
+            "\"{3}\" is an "
+            "incomplete objc type, complete type is {4:x8}",
+            static_cast<void *>(this), die.GetOffset(),
+            DW_TAG_value_to_name(tag), attrs.name.GetCString(),
+            type_sp->GetID());
+      }
+    }
+  }
+  bool is_forward_declaration =
+      attrs.is_forward_declaration ||
+      (attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
+       !die.HasChildren() &&
+       SymbolFileDWARF::GetLanguage(*die.GetCU()) == eLanguageTypeObjC);
+  if (is_forward_declaration) {
+    type_sp = FindDefinitionTypeForDWARFDeclContext(die);
+    if (!type_sp) {
+      SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
+      if (debug_map_symfile) {
+        // We weren't able to find a full declaration in this DWARF, see
+        // if we have a declaration anywhere else...
+        type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die);
+      }
+      if (type_sp && log) {
+        GetObjectFile()->GetModule()->LogMessage(
+            log,
+            "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+            "forward declaration, complete type is {4:x8}",
+            static_cast<void *>(this), die.GetOffset(),
+            DW_TAG_value_to_name(tag), attrs.name.GetCString(),
+            type_sp->GetID());
+      }
+    }
+  }
+  def_die_it = GetDeclarationDIEToDefinitionDIE().find(die.GetDIE());
+  if (def_die_it != GetDeclarationDIEToDefinitionDIE().end())
+    return GetDIE(def_die_it->getSecond());
+
+  if (log) {
+    GetObjectFile()->GetModule()->LogMessage(
+        log,
+        "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+        "forward declaration, unable to find definition DIE for it",
+        static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
+        attrs.name.GetCString());
+  }
+  return DWARFDIE();
+}
+
 Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
                                    bool assert_not_being_parsed,
                                    bool resolve_function_context) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 7282c08c6857c..86d5a3d4f6c46 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -182,6 +182,8 @@ class SymbolFileDWARF : public SymbolFileCommon {
   void FindFunctions(const RegularExpression &regex, bool include_inlines,
                      SymbolContextList &sc_list) override;
 
+  DWARFDIE FindDefinitionDIE(const DWARFDIE &die);
+
   void
   GetMangledNamesForFunction(const std::string &scope_qualified_name,
                              std::vector<ConstString> &mangled_names) override;
@@ -342,6 +344,11 @@ class SymbolFileDWARF : public SymbolFileCommon {
     return m_forward_decl_compiler_type_to_die;
   }
 
+  typedef llvm::DenseMap<const DWARFDebugInfoEntry *, DIERef> DIEToDIE;
+  virtual DIEToDIE &GetDeclarationDIEToDefinitionDIE() {
+    return m_die_to_def_die;
+  }
+
   typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP>
       DIEToVariableSP;
 
@@ -533,9 +540,16 @@ class SymbolFileDWARF : public SymbolFileCommon {
   NameToOffsetMap m_function_scope_qualified_name_map;
   std::unique_ptr<DWARFDebugRanges> m_ranges;
   UniqueDWARFASTTypeMap m_unique_ast_type_map;
+  // A map from DIE to lldb_private::Type. For record type, the key might be
+  // either declaration DIE or definition DIE.
   DIEToTypePtr m_die_to_type;
   DIEToVariableSP m_die_to_variable_sp;
+  // A map from CompilerType to the struct/class/union/enum DIE (might be a
+  // declaration or a definition) that is used to construct it.
   CompilerTypeToDIE m_forward_decl_compiler_type_to_die;
+  // A map from a struct/class/union/enum DIE (might be a declaration or a
+  // definition) to its definition DIE.
+  DIEToDIE m_die_to_def_die;
   llvm::DenseMap<dw_offset_t, std::unique_ptr<SupportFileList>>
       m_type_unit_support_files;
   std::vector<uint32_t> m_lldb_cu_to_dwarf_unit;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index 85e1afd0d8976..cb5ec4ae026b3 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -110,6 +110,11 @@ SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() {
   return GetBaseSymbolFile().GetDIEToVariable();
 }
 
+SymbolFileDWARF::DIEToDIE &
+SymbolFileDWARFDwo::GetDeclarationDIEToDefinitionDIE() {
+  return GetBaseSymbolFile().GetDeclarationDIEToDefinitionDIE();
+}
+
 SymbolFileDWARF::CompilerTypeToDIE &
 SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() {
   return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index 1500540424b52..3e8cfb885aaee 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -74,6 +74,8 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
 
   CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override;
 
+  DIEToDIE &GetDeclarationDIEToDefinitionDIE() override;
+
   UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override;
 
   lldb::TypeSP
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 223518f0ae824..cc23bb86f6805 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -16,60 +16,65 @@ using namespace lldb_private::plugin::dwarf;
 bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
                                   const lldb_private::Declaration &decl,
                                   const int32_t byte_size,
+                                  bool is_forward_declaration,
                                   UniqueDWARFASTType &entry) const {
   for (const UniqueDWARFASTType &udt : m_collection) {
     // Make sure the tags match
     if (udt.m_die.Tag() == die.Tag()) {
-      // Validate byte sizes of both types only if both are valid.
-      if (udt.m_byte_size < 0 || byte_size < 0 ||
-          udt.m_byte_size == byte_size) {
-        // Make sure the file and line match
-        if (udt.m_declaration == decl) {
-          // The type has the same name, and was defined on the same file and
-          // line. Now verify all of the parent DIEs match.
-          DWARFDIE parent_arg_die = die.GetParent();
-          DWARFDIE parent_pos_die = udt.m_die.GetParent();
-          bool match = true;
-          bool done = false;
-          while (!done && match && parent_arg_die && parent_pos_die) {
-            const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
-            const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
-            if (parent_arg_tag == parent_pos_tag) {
-              switch (parent_arg_tag) {
-              case DW_TAG_class_type:
-              case DW_TAG_structure_type:
-              case DW_TAG_union_type:
-              case DW_TAG_namespace: {
-                const char *parent_arg_die_name = parent_arg_die.GetName();
-                if (parent_arg_die_name ==
-                    nullptr) // Anonymous (i.e. no-name) struct
-                {
+      // If they are not both definition DIEs or both declaration DIEs, then
+      // don't check for byte size and declaration location, because declaration
+      // DIEs usually don't have those info.
+      bool matching_size_declaration =
+          udt.m_is_forward_declaration != is_forward_declaration
+              ? true
+              : (udt.m_byte_size < 0 || byte_size < 0 ||
+                 udt.m_byte_size == byte_size) &&
+                    udt.m_declaration == decl;
+      if (matching_size_declaration) {
+        // The type has the same name, and was defined on the same file and
+        // line. Now verify all of the parent DIEs match.
+        DWARFDIE parent_arg_die = die.GetParent();
+        DWARFDIE parent_pos_die = udt.m_die.GetParent();
+        bool match = true;
+        bool done = false;
+        while (!done && match && parent_arg_die && parent_pos_die) {
+          const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
+          const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
+          if (parent_arg_tag == parent_pos_tag) {
+            switch (parent_arg_tag) {
+            case DW_TAG_class_type:
+            case DW_TAG_structure_type:
+            case DW_TAG_union_type:
+            case DW_TAG_namespace: {
+              const char *parent_arg_die_name = parent_arg_die.GetName();
+              if (parent_arg_die_name ==
+                  nullptr) // Anonymous (i.e. no-name) struct
+              {
+                match = false;
+              } else {
+                const char *parent_pos_die_name = parent_pos_die.GetName();
+                if (parent_pos_die_name == nullptr ||
+                    ((parent_arg_die_name != parent_pos_die_name) &&
+                     strcmp(parent_arg_die_name, parent_pos_die_name)))
                   match = false;
-                } else {
-                  const char *parent_pos_die_name = parent_pos_die.GetName();
-                  if (parent_pos_die_name == nullptr ||
-                      ((parent_arg_die_name != parent_pos_die_name) &&
-                       strcmp(parent_arg_die_name, parent_pos_die_name)))
-                    match = false;
-                }
-              } break;
-
-              case DW_TAG_compile_unit:
-              case DW_TAG_partial_unit:
-                done = true;
-                break;
-              default:
-                break;
               }
+            } break;
+
+            case DW_TAG_compile_unit:
+            case DW_TAG_partial_unit:
+              done = true;
+              break;
+            default:
+              break;
             }
-            parent_arg_die = parent_arg_die.GetParent();
-            parent_pos_die = parent_pos_die.GetParent();
           }
+          parent_arg_die = parent_arg_die.GetParent();
+          parent_pos_die = parent_pos_die.GetParent();
+        }
 
-          if (match) {
-            entry = udt;
-            return true;
-          }
+        if (match) {
+          entry = udt;
+          return true;
         }
       }
     }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
index bf3cbae55e5c7..94619953d07ac 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
@@ -24,13 +24,16 @@ class UniqueDWARFASTType {
   UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {}
 
   UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die,
-                     const Declaration &decl, int32_t byte_size)
+                     const Declaration &decl, int32_t byte_size,
+                     bool is_forward_declaration)
       : m_type_sp(type_sp), m_die(die), m_declaration(decl),
-        m_byte_size(byte_size) {}
+        m_byte_size(byte_size),
+        m_is_forward_declaration(is_forward_declaration) {}
 
   UniqueDWARFASTType(const UniqueDWARFASTType &rhs)
       : m_type_sp(rhs.m_type_sp), m_die(rhs.m_die),
-        m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size) {}
+        m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size),
+        m_is_forward_declaration(rhs.m_is_forward_declaration) {}
 
   ~UniqueDWARFASTType() = default;
 
@@ -40,6 +43,7 @@ class UniqueDWARFASTType {
       m_die = rhs.m_die;
       m_declaration = rhs.m_declaration;
       m_byte_size = rhs.m_byte_size;
+      m_is_forward_declaration = rhs.m_is_forward_declaration;
     }
     return *this;
   }
@@ -48,6 +52,8 @@ class UniqueDWARFASTType {
   DWARFDIE m_die;
   Declaration m_declaration;
   int32_t m_byte_size = -1;
+  // True if the m_die is a forward declaration DIE.
+  bool m_is_forward_declaration = true;
 };
 
 class UniqueDWARFASTTypeList {
@@ -63,7 +69,8 @@ class UniqueDWARFASTTypeList {
   }
 
   bool Find(const DWARFDIE &die, const Declaration &decl,
-            const int32_t byte_size, UniqueDWARFASTType &entry) const;
+            const int32_t byte_size, bool is_forward_declaration,
+            UniqueDWARFASTType &entry) const;
 
 protected:
   typedef std::vector<UniqueDWARFASTType> collection;
@@ -81,11 +88,13 @@ class UniqueDWARFASTTypeMap {
   }
 
   bool Find(ConstString name, const DWARFDIE &die, const Declaration &decl,
-            const int32_t byte_size, UniqueDWARFASTType &entry) const {
+            const int32_t byte_size, bool is_forward_declaration,
+            UniqueDWARFASTType &entry) const {
     const char *unique_name_cstr = name.GetCString();
     collection::const_iterator pos = m_collection.find(unique_name_cstr);
     if (pos != m_collection.end()) {
-      return pos->second.Find(die, decl, byte_size, entry);
+      return pos->second.Find(die, decl, byte_size, is_forward_declaration,
+                              entry);
     }
     return false;
   }

>From 751a58d24ec9e32234d2bfa672f51d255bfd78fa Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Wed, 1 May 2024 10:25:28 -0400
Subject: [PATCH 2/8] fix format

---
 lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 5a317db7e7402..c7069550ccf70 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1689,12 +1689,10 @@ DWARFDIE SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
       // and this DIE isn't the complete definition (we checked
       // is_complete_objc_class above and know it is false), so the real
       // definition is in here somewhere
-      type_sp =
-          FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
+      type_sp = FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
 
       if (!type_sp) {
-        SymbolFileDWARFDebugMap *debug_map_symfile =
-            GetDebugMapSymfile();
+        SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
         if (debug_map_symfile) {
           // We weren't able to find a full declaration in this DWARF,
           // see if we have a declaration anywhere else...

>From c0a539ec9b3b468e5568cd6f569f51663fdafcac Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Thu, 2 May 2024 14:08:11 -0400
Subject: [PATCH 3/8] address comments

---
 .../Plugins/SymbolFile/DWARF/DWARFASTParser.h |   6 +
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  | 166 ++++++++++++++----
 .../SymbolFile/DWARF/DWARFASTParserClang.h    |  10 ++
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      | 146 ++++-----------
 .../SymbolFile/DWARF/SymbolFileDWARF.h        |  10 --
 .../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp   |   5 -
 .../SymbolFile/DWARF/SymbolFileDWARFDwo.h     |   2 -
 7 files changed, 179 insertions(+), 166 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
index 66db396279e06..14b9cba05d321 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -60,6 +60,12 @@ class DWARFASTParser {
 
   virtual ConstString GetDIEClassTemplateParams(const DWARFDIE &die) = 0;
 
+  // Return true if we found the definition DIE for it. is_forward_declaration
+  // is set to true if the parameter die is a declaration.
+  virtual bool
+  FindDefinitionDIE(const lldb_private::plugin::dwarf::DWARFDIE &die,
+                    bool &is_forward_declaration) = 0;
+
   static std::optional<SymbolFile::ArrayInfo>
   ParseChildArrayInfo(const DWARFDIE &parent_die,
                       const ExecutionContext *exe_ctx = nullptr);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 7ad661c9a9d49..8a8c303e1a8b2 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -154,6 +154,27 @@ static bool TagIsRecordType(dw_tag_t tag) {
   }
 }
 
+static bool
+IsForwardDeclaration(const lldb_private::plugin::dwarf::DWARFDIE &die,
+                     const ParsedDWARFTypeAttributes &attrs,
+                     LanguageType cu_language) {
+  if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
+      !die.HasChildren() && cu_language == eLanguageTypeObjC) {
+    // Work around an issue with clang at the moment where forward
+    // declarations for objective C classes are emitted as:
+    //  DW_TAG_structure_type [2]
+    //  DW_AT_name( "ForwardObjcClass" )
+    //  DW_AT_byte_size( 0x00 )
+    //  DW_AT_decl_file( "..." )
+    //  DW_AT_decl_line( 1 )
+    //
+    // Note that there is no DW_AT_declaration and there are no children,
+    // and the byte size is zero.
+    return true;
+  }
+  return attrs.is_forward_declaration;
+}
+
 TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
                                                      const DWARFDIE &die,
                                                      Log *log) {
@@ -249,12 +270,10 @@ static void ForcefullyCompleteType(CompilerType type) {
 /// This function serves a similar purpose as RequireCompleteType above, but it
 /// avoids completing the type if it is not immediately necessary. It only
 /// ensures we _can_ complete the type later.
-static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
-                                           ClangASTImporter &ast_importer,
-                                           clang::DeclContext *decl_ctx,
-                                           const DWARFDIE &decl_ctx_die,
-                                           const DWARFDIE &die,
-                                           const char *type_name_cstr) {
+void DWARFASTParserClang::PrepareContextToReceiveMembers(
+    TypeSystemClang &ast, clang::DeclContext *decl_ctx,
+    const DWARFDIE &decl_ctx_die, const DWARFDIE &die,
+    const char *type_name_cstr) {
   auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);
   if (!tag_decl_ctx)
     return; // Non-tag context are always ready.
@@ -270,6 +289,7 @@ static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
 
   // If this type was not imported from an external AST, there's nothing to do.
   CompilerType type = ast.GetTypeForDecl(tag_decl_ctx);
+  ClangASTImporter &ast_importer = GetClangASTImporter();
   if (type && ast_importer.CanImport(type)) {
     auto qual_type = ClangUtil::GetQualType(type);
     if (ast_importer.RequireCompleteType(qual_type))
@@ -284,7 +304,8 @@ static void PrepareContextToReceiveMembers(TypeSystemClang &ast,
   // 1. Found the the definition DIE and start its definition with
   // TypeSystemClang::StartTagDeclarationDefinition.
   // 2. Unable to find it, then need to forcefully complete it.
-  die.GetDWARF()->FindDefinitionDIE(decl_ctx_die);
+  bool is_forward_declaration = false;
+  FindDefinitionDIE(decl_ctx_die, is_forward_declaration);
   if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined())
     return;
   // We don't have a type definition and/or the import failed. We must
@@ -631,8 +652,8 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
     DWARFDIE decl_ctx_die;
     clang::DeclContext *decl_ctx =
         GetClangDeclContextContainingDIE(die, &decl_ctx_die);
-    PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx,
-                                   decl_ctx_die, die, attrs.name.GetCString());
+    PrepareContextToReceiveMembers(m_ast, decl_ctx, decl_ctx_die, die,
+                                   attrs.name.GetCString());
 
     if (attrs.type.IsValid()) {
       // Try to parse a typedef from the (DWARF embedded in the) Clang
@@ -1648,6 +1669,96 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
   return qualified_name;
 }
 
+bool DWARFASTParserClang::FindDefinitionDIE(const DWARFDIE &die,
+                                            bool &is_forward_declaration) {
+  ParsedDWARFTypeAttributes attrs(die);
+  is_forward_declaration = IsForwardDeclaration(
+      die, attrs, SymbolFileDWARF::GetLanguage(*die.GetCU()));
+  if (!is_forward_declaration)
+    return true;
+
+  const dw_tag_t tag = die.Tag();
+  TypeSP type_sp;
+  SymbolFileDWARF *dwarf = die.GetDWARF();
+  Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
+  if (log) {
+    dwarf->GetObjectFile()->GetModule()->LogMessage(
+        log,
+        "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+        "forward declaration DIE, trying to find definition DIE",
+        static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
+        attrs.name.GetCString());
+  }
+  // We haven't parse definition die for this type, starting to search for it.
+  // After we found the definition die, the GetDeclarationDIEToDefinitionDIE()
+  // map will have the new mapping from this declaration die to definition die.
+  if (attrs.class_language == eLanguageTypeObjC ||
+      attrs.class_language == eLanguageTypeObjC_plus_plus) {
+    if (!attrs.is_complete_objc_class &&
+        die.Supports_DW_AT_APPLE_objc_complete_type()) {
+      // We have a valid eSymbolTypeObjCClass class symbol whose name
+      // matches the current objective C class that we are trying to find
+      // and this DIE isn't the complete definition (we checked
+      // is_complete_objc_class above and know it is false), so the real
+      // definition is in here somewhere
+      type_sp =
+          dwarf->FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
+
+      if (!type_sp) {
+        SymbolFileDWARFDebugMap *debug_map_symfile =
+            dwarf->GetDebugMapSymfile();
+        if (debug_map_symfile) {
+          // We weren't able to find a full declaration in this DWARF,
+          // see if we have a declaration anywhere else...
+          type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE(
+              die, attrs.name, true);
+        }
+      }
+
+      if (type_sp && log) {
+        dwarf->GetObjectFile()->GetModule()->LogMessage(
+            log,
+            "SymbolFileDWARF({0:p}) - {1:x16}: {2} type "
+            "\"{3}\" is an "
+            "incomplete objc type, complete type is {4:x8}",
+            static_cast<void *>(this), die.GetOffset(),
+            DW_TAG_value_to_name(tag), attrs.name.GetCString(),
+            type_sp->GetID());
+      }
+    }
+  }
+
+  type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die);
+  if (!type_sp) {
+    SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
+    if (debug_map_symfile) {
+      // We weren't able to find a full declaration in this DWARF, see
+      // if we have a declaration anywhere else...
+      type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die);
+    }
+    if (type_sp && log) {
+      dwarf->GetObjectFile()->GetModule()->LogMessage(
+          log,
+          "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+          "forward declaration, complete type is {4:x8}",
+          static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
+          attrs.name.GetCString(), type_sp->GetID());
+    }
+  }
+  if (type_sp)
+    return true;
+
+  if (log) {
+    dwarf->GetObjectFile()->GetModule()->LogMessage(
+        log,
+        "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
+        "forward declaration, unable to find definition DIE for it",
+        static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
+        attrs.name.GetCString());
+  }
+  return false;
+}
+
 TypeSP
 DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
                                            const DWARFDIE &die,
@@ -1668,6 +1779,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
   ConstString unique_typename(attrs.name);
   Declaration unique_decl(attrs.decl);
   uint64_t byte_size = attrs.byte_size.value_or(0);
+  attrs.is_forward_declaration = IsForwardDeclaration(die, attrs, cu_language);
 
   if (attrs.name) {
     if (Language::LanguageIsCPlusPlus(cu_language)) {
@@ -1689,8 +1801,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
         LinkDeclContextToDIE(
             GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die);
         if (!attrs.is_forward_declaration) {
-          dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace(
-              unique_ast_entry_up->m_die.GetDIE(), *die.GetDIERef());
           // If the parameter DIE is definition and the entry in the map is
           // declaration, then we need to update the entry to point to the
           // definition DIE.
@@ -1703,10 +1813,18 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
             // it's used in ParseSubroutine to determine if we need to copy cxx
             // method types from a declaration DIE to this definition DIE.
             type_sp->SetID(die.GetID());
+            clang_type = type_sp->GetForwardCompilerType();
             if (attrs.class_language != eLanguageTypeObjC &&
                 attrs.class_language != eLanguageTypeObjC_plus_plus)
-              TypeSystemClang::StartTagDeclarationDefinition(
-                  type_sp->GetForwardCompilerType());
+              TypeSystemClang::StartTagDeclarationDefinition(clang_type);
+
+            CompilerType compiler_type_no_qualifiers =
+                ClangUtil::RemoveFastQualifiers(clang_type);
+            auto result = dwarf->GetForwardDeclCompilerTypeToDIE().try_emplace(
+                compiler_type_no_qualifiers.GetOpaqueQualType(),
+                *die.GetDIERef());
+            if (!result.second)
+              result.first->second = *die.GetDIERef();
           }
         }
         return type_sp;
@@ -1730,21 +1848,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
     default_accessibility = eAccessPrivate;
   }
 
-  if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
-      !die.HasChildren() && cu_language == eLanguageTypeObjC) {
-    // Work around an issue with clang at the moment where forward
-    // declarations for objective C classes are emitted as:
-    //  DW_TAG_structure_type [2]
-    //  DW_AT_name( "ForwardObjcClass" )
-    //  DW_AT_byte_size( 0x00 )
-    //  DW_AT_decl_file( "..." )
-    //  DW_AT_decl_line( 1 )
-    //
-    // Note that there is no DW_AT_declaration and there are no children,
-    // and the byte size is zero.
-    attrs.is_forward_declaration = true;
-  }
-
   if (attrs.is_forward_declaration) {
     // See if the type comes from a Clang module and if so, track down
     // that type.
@@ -1759,8 +1862,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
   clang::DeclContext *decl_ctx =
       GetClangDeclContextContainingDIE(die, &decl_ctx_die);
 
-  PrepareContextToReceiveMembers(m_ast, GetClangASTImporter(), decl_ctx,
-                                 decl_ctx_die, die, attrs.name.GetCString());
+  PrepareContextToReceiveMembers(m_ast, decl_ctx, decl_ctx_die, die,
+                                 attrs.name.GetCString());
 
   if (attrs.accessibility == eAccessNone && decl_ctx) {
     // Check the decl context that contains this class/struct/union. If
@@ -1809,9 +1912,6 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
         attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata,
         attrs.exports_symbols);
   }
-  if (!attrs.is_forward_declaration)
-    dwarf->GetDeclarationDIEToDefinitionDIE().try_emplace(die.GetDIE(),
-                                                          *die.GetDIERef());
   // Store a forward declaration to this class type in case any
   // parameters in any class methods need it for the clang types for
   // function prototypes.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 8d4af203bb287..b884d6869add8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -108,6 +108,9 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
   lldb_private::ConstString GetDIEClassTemplateParams(
       const lldb_private::plugin::dwarf::DWARFDIE &die) override;
 
+  bool FindDefinitionDIE(const lldb_private::plugin::dwarf::DWARFDIE &die,
+                         bool &is_forward_declaration) override;
+
 protected:
   /// Protected typedefs and members.
   /// @{
@@ -246,6 +249,13 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
   lldb::ModuleSP
   GetModuleForType(const lldb_private::plugin::dwarf::DWARFDIE &die);
 
+  void PrepareContextToReceiveMembers(
+      lldb_private::TypeSystemClang &ast,
+      clang::DeclContext *decl_ctx,
+      const lldb_private::plugin::dwarf::DWARFDIE &decl_ctx_die,
+      const lldb_private::plugin::dwarf::DWARFDIE &die,
+      const char *type_name_cstr);
+
   static bool classof(const DWARFASTParser *Parser) {
     return Parser->GetKind() == Kind::DWARFASTParserClang;
   }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index c7069550ccf70..d2f66b00c1794 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1631,126 +1631,40 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
     return true;
   }
 
-  DWARFDIE dwarf_die = FindDefinitionDIE(GetDIE(die_it->getSecond()));
-  if (dwarf_die) {
-    // Once we start resolving this type, remove it from the forward
-    // declaration map in case anyone child members or other types require this
-    // type to get resolved. The type will get resolved when all of the calls
-    // to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
-    // Need to get a new iterator because FindDefinitionDIE might add new
-    // entries into the map and invalidate previous iterator.
-    auto die_it = GetForwardDeclCompilerTypeToDIE().find(
-        compiler_type_no_qualifiers.GetOpaqueQualType());
-    if (die_it != GetForwardDeclCompilerTypeToDIE().end()) {
-      GetForwardDeclCompilerTypeToDIE().erase(die_it);
-    }
-
-    Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
+  // Once we start resolving this type, remove it from the forward
+  // declaration map in case anyone child members or other types require this
+  // type to get resolved.
+  DWARFDIE dwarf_die = GetDIE(die_it->second);
+  GetForwardDeclCompilerTypeToDIE().erase(die_it);
+  // The DWARFASTParser might determine if this is a declaration or not with
+  // information other than DW_AT_declaration depending on the language.
+  bool is_forward_declaration = false;
+  bool found_def_die = false;
+  if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
+    found_def_die =
+        dwarf_ast->FindDefinitionDIE(dwarf_die, is_forward_declaration);
+  if (!found_def_die)
+    return false;
 
-    Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
-    if (log)
-      GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
-          log, "{0:x8}: {1} '{2}' resolving forward declaration...",
-          dwarf_die.GetID(), dwarf_die.GetTagAsCString(),
-          type->GetName().AsCString());
-    assert(compiler_type);
-    if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
-      return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
+  die_it = GetForwardDeclCompilerTypeToDIE().find(
+      compiler_type_no_qualifiers.GetOpaqueQualType());
+  if (die_it != GetForwardDeclCompilerTypeToDIE().end()) {
+    dwarf_die = GetDIE(die_it->getSecond());
+    GetForwardDeclCompilerTypeToDIE().erase(die_it);
   }
-  return false;
-}
 
-DWARFDIE SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) {
-  auto def_die_it = GetDeclarationDIEToDefinitionDIE().find(die.GetDIE());
-  if (def_die_it != GetDeclarationDIEToDefinitionDIE().end())
-    return GetDIE(def_die_it->getSecond());
+  Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
 
-  ParsedDWARFTypeAttributes attrs(die);
-  const dw_tag_t tag = die.Tag();
-  TypeSP type_sp;
-  Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
-  if (log) {
-    GetObjectFile()->GetModule()->LogMessage(
-        log,
-        "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
-        "forward declaration DIE, trying to find definition DIE",
-        static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
-        attrs.name.GetCString());
-  }
-  // We haven't parse definition die for this type, starting to search for it.
-  // After we found the definition die, the GetDeclarationDIEToDefinitionDIE()
-  // map will have the new mapping from this declaration die to definition die.
-  if (attrs.class_language == eLanguageTypeObjC ||
-      attrs.class_language == eLanguageTypeObjC_plus_plus) {
-    if (!attrs.is_complete_objc_class &&
-        die.Supports_DW_AT_APPLE_objc_complete_type()) {
-      // We have a valid eSymbolTypeObjCClass class symbol whose name
-      // matches the current objective C class that we are trying to find
-      // and this DIE isn't the complete definition (we checked
-      // is_complete_objc_class above and know it is false), so the real
-      // definition is in here somewhere
-      type_sp = FindCompleteObjCDefinitionTypeForDIE(die, attrs.name, true);
-
-      if (!type_sp) {
-        SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
-        if (debug_map_symfile) {
-          // We weren't able to find a full declaration in this DWARF,
-          // see if we have a declaration anywhere else...
-          type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE(
-              die, attrs.name, true);
-        }
-      }
-
-      if (type_sp && log) {
-        GetObjectFile()->GetModule()->LogMessage(
-            log,
-            "SymbolFileDWARF({0:p}) - {1:x16}: {2} type "
-            "\"{3}\" is an "
-            "incomplete objc type, complete type is {4:x8}",
-            static_cast<void *>(this), die.GetOffset(),
-            DW_TAG_value_to_name(tag), attrs.name.GetCString(),
-            type_sp->GetID());
-      }
-    }
-  }
-  bool is_forward_declaration =
-      attrs.is_forward_declaration ||
-      (attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
-       !die.HasChildren() &&
-       SymbolFileDWARF::GetLanguage(*die.GetCU()) == eLanguageTypeObjC);
-  if (is_forward_declaration) {
-    type_sp = FindDefinitionTypeForDWARFDeclContext(die);
-    if (!type_sp) {
-      SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
-      if (debug_map_symfile) {
-        // We weren't able to find a full declaration in this DWARF, see
-        // if we have a declaration anywhere else...
-        type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(die);
-      }
-      if (type_sp && log) {
-        GetObjectFile()->GetModule()->LogMessage(
-            log,
-            "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
-            "forward declaration, complete type is {4:x8}",
-            static_cast<void *>(this), die.GetOffset(),
-            DW_TAG_value_to_name(tag), attrs.name.GetCString(),
-            type_sp->GetID());
-      }
-    }
-  }
-  def_die_it = GetDeclarationDIEToDefinitionDIE().find(die.GetDIE());
-  if (def_die_it != GetDeclarationDIEToDefinitionDIE().end())
-    return GetDIE(def_die_it->getSecond());
-
-  if (log) {
-    GetObjectFile()->GetModule()->LogMessage(
-        log,
-        "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
-        "forward declaration, unable to find definition DIE for it",
-        static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
-        attrs.name.GetCString());
-  }
-  return DWARFDIE();
+  Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
+  if (log)
+    GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
+        log, "{0:x8}: {1} '{2}' resolving forward declaration...",
+        dwarf_die.GetID(), dwarf_die.GetTagAsCString(),
+        type->GetName().AsCString());
+  assert(compiler_type);
+  if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
+    return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type);
+  return true;
 }
 
 Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 86d5a3d4f6c46..94aa810680c52 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -182,8 +182,6 @@ class SymbolFileDWARF : public SymbolFileCommon {
   void FindFunctions(const RegularExpression &regex, bool include_inlines,
                      SymbolContextList &sc_list) override;
 
-  DWARFDIE FindDefinitionDIE(const DWARFDIE &die);
-
   void
   GetMangledNamesForFunction(const std::string &scope_qualified_name,
                              std::vector<ConstString> &mangled_names) override;
@@ -344,11 +342,6 @@ class SymbolFileDWARF : public SymbolFileCommon {
     return m_forward_decl_compiler_type_to_die;
   }
 
-  typedef llvm::DenseMap<const DWARFDebugInfoEntry *, DIERef> DIEToDIE;
-  virtual DIEToDIE &GetDeclarationDIEToDefinitionDIE() {
-    return m_die_to_def_die;
-  }
-
   typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP>
       DIEToVariableSP;
 
@@ -547,9 +540,6 @@ class SymbolFileDWARF : public SymbolFileCommon {
   // A map from CompilerType to the struct/class/union/enum DIE (might be a
   // declaration or a definition) that is used to construct it.
   CompilerTypeToDIE m_forward_decl_compiler_type_to_die;
-  // A map from a struct/class/union/enum DIE (might be a declaration or a
-  // definition) to its definition DIE.
-  DIEToDIE m_die_to_def_die;
   llvm::DenseMap<dw_offset_t, std::unique_ptr<SupportFileList>>
       m_type_unit_support_files;
   std::vector<uint32_t> m_lldb_cu_to_dwarf_unit;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index cb5ec4ae026b3..85e1afd0d8976 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -110,11 +110,6 @@ SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() {
   return GetBaseSymbolFile().GetDIEToVariable();
 }
 
-SymbolFileDWARF::DIEToDIE &
-SymbolFileDWARFDwo::GetDeclarationDIEToDefinitionDIE() {
-  return GetBaseSymbolFile().GetDeclarationDIEToDefinitionDIE();
-}
-
 SymbolFileDWARF::CompilerTypeToDIE &
 SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() {
   return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index 3e8cfb885aaee..1500540424b52 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -74,8 +74,6 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
 
   CompilerTypeToDIE &GetForwardDeclCompilerTypeToDIE() override;
 
-  DIEToDIE &GetDeclarationDIEToDefinitionDIE() override;
-
   UniqueDWARFASTTypeMap &GetUniqueDWARFASTTypeMap() override;
 
   lldb::TypeSP

>From 515c85d30fbacb523d51b024010056a61956e93b Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Fri, 3 May 2024 10:39:07 -0400
Subject: [PATCH 4/8] Address comments

---
 .../Plugins/SymbolFile/DWARF/DWARFASTParser.h |   6 +-
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  |  68 +++---
 .../SymbolFile/DWARF/DWARFASTParserClang.h    | 203 ++++++++----------
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      |  12 +-
 .../SymbolFile/DWARF/UniqueDWARFASTType.cpp   |  82 +++----
 5 files changed, 163 insertions(+), 208 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
index 14b9cba05d321..e144cf0f9bd94 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -60,11 +60,7 @@ class DWARFASTParser {
 
   virtual ConstString GetDIEClassTemplateParams(const DWARFDIE &die) = 0;
 
-  // Return true if we found the definition DIE for it. is_forward_declaration
-  // is set to true if the parameter die is a declaration.
-  virtual bool
-  FindDefinitionDIE(const lldb_private::plugin::dwarf::DWARFDIE &die,
-                    bool &is_forward_declaration) = 0;
+  virtual lldb_private::Type *FindDefinitionTypeForDIE(const DWARFDIE &die) = 0;
 
   static std::optional<SymbolFile::ArrayInfo>
   ParseChildArrayInfo(const DWARFDIE &parent_die,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 8a8c303e1a8b2..0db2e7984d13e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -271,9 +271,8 @@ static void ForcefullyCompleteType(CompilerType type) {
 /// avoids completing the type if it is not immediately necessary. It only
 /// ensures we _can_ complete the type later.
 void DWARFASTParserClang::PrepareContextToReceiveMembers(
-    TypeSystemClang &ast, clang::DeclContext *decl_ctx,
-    const DWARFDIE &decl_ctx_die, const DWARFDIE &die,
-    const char *type_name_cstr) {
+    clang::DeclContext *decl_ctx, const DWARFDIE &decl_ctx_die,
+    const DWARFDIE &die, const char *type_name_cstr) {
   auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);
   if (!tag_decl_ctx)
     return; // Non-tag context are always ready.
@@ -288,7 +287,7 @@ void DWARFASTParserClang::PrepareContextToReceiveMembers(
   // gmodules case), we can complete the type by doing a full import.
 
   // If this type was not imported from an external AST, there's nothing to do.
-  CompilerType type = ast.GetTypeForDecl(tag_decl_ctx);
+  CompilerType type = m_ast.GetTypeForDecl(tag_decl_ctx);
   ClangASTImporter &ast_importer = GetClangASTImporter();
   if (type && ast_importer.CanImport(type)) {
     auto qual_type = ClangUtil::GetQualType(type);
@@ -304,8 +303,7 @@ void DWARFASTParserClang::PrepareContextToReceiveMembers(
   // 1. Found the the definition DIE and start its definition with
   // TypeSystemClang::StartTagDeclarationDefinition.
   // 2. Unable to find it, then need to forcefully complete it.
-  bool is_forward_declaration = false;
-  FindDefinitionDIE(decl_ctx_die, is_forward_declaration);
+  FindDefinitionTypeForDIE(decl_ctx_die);
   if (tag_decl_ctx->isCompleteDefinition() || tag_decl_ctx->isBeingDefined())
     return;
   // We don't have a type definition and/or the import failed. We must
@@ -652,7 +650,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
     DWARFDIE decl_ctx_die;
     clang::DeclContext *decl_ctx =
         GetClangDeclContextContainingDIE(die, &decl_ctx_die);
-    PrepareContextToReceiveMembers(m_ast, decl_ctx, decl_ctx_die, die,
+    PrepareContextToReceiveMembers(decl_ctx, decl_ctx_die, die,
                                    attrs.name.GetCString());
 
     if (attrs.type.IsValid()) {
@@ -1669,17 +1667,17 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
   return qualified_name;
 }
 
-bool DWARFASTParserClang::FindDefinitionDIE(const DWARFDIE &die,
-                                            bool &is_forward_declaration) {
+lldb_private::Type *
+DWARFASTParserClang::FindDefinitionTypeForDIE(const DWARFDIE &die) {
+  SymbolFileDWARF *dwarf = die.GetDWARF();
   ParsedDWARFTypeAttributes attrs(die);
-  is_forward_declaration = IsForwardDeclaration(
+  bool is_forward_declaration = IsForwardDeclaration(
       die, attrs, SymbolFileDWARF::GetLanguage(*die.GetCU()));
   if (!is_forward_declaration)
-    return true;
+    return dwarf->GetDIEToType()[die.GetDIE()];
 
   const dw_tag_t tag = die.Tag();
   TypeSP type_sp;
-  SymbolFileDWARF *dwarf = die.GetDWARF();
   Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
   if (log) {
     dwarf->GetObjectFile()->GetModule()->LogMessage(
@@ -1745,10 +1743,8 @@ bool DWARFASTParserClang::FindDefinitionDIE(const DWARFDIE &die,
           attrs.name.GetCString(), type_sp->GetID());
     }
   }
-  if (type_sp)
-    return true;
 
-  if (log) {
+  if (!type_sp && log) {
     dwarf->GetObjectFile()->GetModule()->LogMessage(
         log,
         "SymbolFileDWARF({0:p}) - {1:x16}: {2} type \"{3}\" is a "
@@ -1756,7 +1752,7 @@ bool DWARFASTParserClang::FindDefinitionDIE(const DWARFDIE &die,
         static_cast<void *>(this), die.GetOffset(), DW_TAG_value_to_name(tag),
         attrs.name.GetCString());
   }
-  return false;
+  return type_sp.get();
 }
 
 TypeSP
@@ -1801,9 +1797,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
         LinkDeclContextToDIE(
             GetCachedClangDeclContextForDIE(unique_ast_entry_up->m_die), die);
         if (!attrs.is_forward_declaration) {
-          // If the parameter DIE is definition and the entry in the map is
-          // declaration, then we need to update the entry to point to the
-          // definition DIE.
+          // If the DIE being parsed in this function is a definition and the
+          // entry in the map is a declaration, then we need to update the entry
+          // to point to the definition DIE.
           if (unique_ast_entry_up->m_is_forward_declaration) {
             unique_ast_entry_up->m_die = die;
             unique_ast_entry_up->m_byte_size = byte_size;
@@ -1862,7 +1858,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
   clang::DeclContext *decl_ctx =
       GetClangDeclContextContainingDIE(die, &decl_ctx_die);
 
-  PrepareContextToReceiveMembers(m_ast, decl_ctx, decl_ctx_die, die,
+  PrepareContextToReceiveMembers(decl_ctx, decl_ctx_die, die,
                                  attrs.name.GetCString());
 
   if (attrs.accessibility == eAccessNone && decl_ctx) {
@@ -1970,25 +1966,25 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
           GetClangASTImporter().SetRecordLayout(record_decl, layout);
         }
       }
-    }
-    // Start the definition if the class is not objective C since the
-    // underlying decls respond to isCompleteDefinition(). Objective
-    // C decls don't respond to isCompleteDefinition() so we can't
-    // start the declaration definition right away. For C++
-    // class/union/structs we want to start the definition in case the
-    // class is needed as the declaration context for a contained class
-    // or type without the need to complete that type..
+    } else {
+      // Start the definition if the class is not objective C since the
+      // underlying decls respond to isCompleteDefinition(). Objective
+      // C decls don't respond to isCompleteDefinition() so we can't
+      // start the declaration definition right away. For C++
+      // class/union/structs we want to start the definition in case the
+      // class is needed as the declaration context for a contained class
+      // or type without the need to complete that type..
 
-    if (attrs.class_language != eLanguageTypeObjC &&
-        attrs.class_language != eLanguageTypeObjC_plus_plus)
-      TypeSystemClang::StartTagDeclarationDefinition(clang_type);
+      if (attrs.class_language != eLanguageTypeObjC &&
+          attrs.class_language != eLanguageTypeObjC_plus_plus)
+        TypeSystemClang::StartTagDeclarationDefinition(clang_type);
+    }
   }
 
-  // Leave this as a forward declaration until we need to know the
-  // details of the type. lldb_private::Type will automatically call
-  // the SymbolFile virtual function
-  // "SymbolFileDWARF::CompleteType(Type *)" When the definition
-  // needs to be defined.
+  // If this is a declaration DIE, leave this as a forward declaration until we
+  // need to know the details of the type. lldb_private::Type will automatically
+  // call the SymbolFile virtual function "SymbolFileDWARF::CompleteType(Type
+  // *)" When the definition needs to be defined.
   assert(!dwarf->GetForwardDeclCompilerTypeToDIE().count(
              ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()) &&
          "Type already in the forward declaration map!");
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index b884d6869add8..853b8ccc30369 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -42,40 +42,40 @@ struct ParsedDWARFTypeAttributes;
 
 class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
 public:
+  typedef lldb_private::plugin::dwarf::DWARFDIE DWARFDIE;
+
   DWARFASTParserClang(lldb_private::TypeSystemClang &ast);
 
   ~DWARFASTParserClang() override;
 
   // DWARFASTParser interface.
-  lldb::TypeSP
-  ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
-                     const lldb_private::plugin::dwarf::DWARFDIE &die,
-                     bool *type_is_new_ptr) override;
+  lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
+                                  const DWARFDIE &die,
+                                  bool *type_is_new_ptr) override;
 
-  lldb_private::ConstString ConstructDemangledNameFromDWARF(
-      const lldb_private::plugin::dwarf::DWARFDIE &die) override;
+  lldb_private::ConstString
+  ConstructDemangledNameFromDWARF(const DWARFDIE &die) override;
 
   lldb_private::Function *
   ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit,
-                         const lldb_private::plugin::dwarf::DWARFDIE &die,
+                         const DWARFDIE &die,
                          const lldb_private::AddressRange &func_range) override;
 
   bool
-  CompleteTypeFromDWARF(const lldb_private::plugin::dwarf::DWARFDIE &die,
-                        lldb_private::Type *type,
+  CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,
                         lldb_private::CompilerType &compiler_type) override;
 
-  lldb_private::CompilerDecl GetDeclForUIDFromDWARF(
-      const lldb_private::plugin::dwarf::DWARFDIE &die) override;
+  lldb_private::CompilerDecl
+  GetDeclForUIDFromDWARF(const DWARFDIE &die) override;
 
   void EnsureAllDIEsInDeclContextHaveBeenParsed(
       lldb_private::CompilerDeclContext decl_context) override;
 
-  lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF(
-      const lldb_private::plugin::dwarf::DWARFDIE &die) override;
+  lldb_private::CompilerDeclContext
+  GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override;
 
-  lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF(
-      const lldb_private::plugin::dwarf::DWARFDIE &die) override;
+  lldb_private::CompilerDeclContext
+  GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override;
 
   lldb_private::ClangASTImporter &GetClangASTImporter();
 
@@ -105,11 +105,13 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
   /// \return A string, including surrounding '<>', of the template parameters.
   /// If the DIE's name already has '<>', returns an empty ConstString because
   /// it's assumed that the caller is using the DIE name anyway.
-  lldb_private::ConstString GetDIEClassTemplateParams(
-      const lldb_private::plugin::dwarf::DWARFDIE &die) override;
+  lldb_private::ConstString
+  GetDIEClassTemplateParams(const DWARFDIE &die) override;
 
-  bool FindDefinitionDIE(const lldb_private::plugin::dwarf::DWARFDIE &die,
-                         bool &is_forward_declaration) override;
+  // Searching for definition DIE for the given DIE and return the type
+  // associated with the definition DIE, or nullptr if definition DIE is not
+  // found.
+  lldb_private::Type *FindDefinitionTypeForDIE(const DWARFDIE &die) override;
 
 protected:
   /// Protected typedefs and members.
@@ -121,8 +123,7 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
       const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *,
       clang::DeclContext *>
       DIEToDeclContextMap;
-  typedef std::multimap<const clang::DeclContext *,
-                        const lldb_private::plugin::dwarf::DWARFDIE>
+  typedef std::multimap<const clang::DeclContext *, const DWARFDIE>
       DeclContextToDIEMap;
   typedef llvm::DenseMap<
       const lldb_private::plugin::dwarf::DWARFDebugInfoEntry *,
@@ -140,14 +141,11 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
   std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_up;
   /// @}
 
-  clang::DeclContext *
-  GetDeclContextForBlock(const lldb_private::plugin::dwarf::DWARFDIE &die);
+  clang::DeclContext *GetDeclContextForBlock(const DWARFDIE &die);
 
-  clang::BlockDecl *
-  ResolveBlockDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);
+  clang::BlockDecl *ResolveBlockDIE(const DWARFDIE &die);
 
-  clang::NamespaceDecl *
-  ResolveNamespaceDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);
+  clang::NamespaceDecl *ResolveNamespaceDIE(const DWARFDIE &die);
 
   /// Returns the namespace decl that a DW_TAG_imported_declaration imports.
   ///
@@ -158,103 +156,86 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
   ///          'die' imports. If the imported entity is not a namespace
   ///          or another import declaration, returns nullptr. If an error
   ///          occurs, returns nullptr.
-  clang::NamespaceDecl *ResolveImportedDeclarationDIE(
-      const lldb_private::plugin::dwarf::DWARFDIE &die);
+  clang::NamespaceDecl *ResolveImportedDeclarationDIE(const DWARFDIE &die);
 
-  bool ParseTemplateDIE(const lldb_private::plugin::dwarf::DWARFDIE &die,
+  bool ParseTemplateDIE(const DWARFDIE &die,
                         lldb_private::TypeSystemClang::TemplateParameterInfos
                             &template_param_infos);
 
   bool ParseTemplateParameterInfos(
-      const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
+      const DWARFDIE &parent_die,
       lldb_private::TypeSystemClang::TemplateParameterInfos
           &template_param_infos);
 
-  std::string
-  GetCPlusPlusQualifiedName(const lldb_private::plugin::dwarf::DWARFDIE &die);
+  std::string GetCPlusPlusQualifiedName(const DWARFDIE &die);
 
   bool ParseChildMembers(
-      const lldb_private::plugin::dwarf::DWARFDIE &die,
-      lldb_private::CompilerType &class_compiler_type,
+      const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type,
       std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
-      std::vector<lldb_private::plugin::dwarf::DWARFDIE> &member_function_dies,
-      std::vector<lldb_private::plugin::dwarf::DWARFDIE> &contained_type_dies,
+      std::vector<DWARFDIE> &member_function_dies,
+      std::vector<DWARFDIE> &contained_type_dies,
       DelayedPropertyList &delayed_properties,
       const lldb::AccessType default_accessibility,
       lldb_private::ClangASTImporter::LayoutInfo &layout_info);
 
   size_t
   ParseChildParameters(clang::DeclContext *containing_decl_ctx,
-                       const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
-                       bool skip_artificial, bool &is_static, bool &is_variadic,
+                       const DWARFDIE &parent_die, bool skip_artificial,
+                       bool &is_static, bool &is_variadic,
                        bool &has_template_params,
                        std::vector<lldb_private::CompilerType> &function_args,
                        std::vector<clang::ParmVarDecl *> &function_param_decls,
                        unsigned &type_quals);
 
-  size_t ParseChildEnumerators(
-      lldb_private::CompilerType &compiler_type, bool is_signed,
-      uint32_t enumerator_byte_size,
-      const lldb_private::plugin::dwarf::DWARFDIE &parent_die);
+  size_t ParseChildEnumerators(lldb_private::CompilerType &compiler_type,
+                               bool is_signed, uint32_t enumerator_byte_size,
+                               const DWARFDIE &parent_die);
 
   /// Parse a structure, class, or union type DIE.
-  lldb::TypeSP
-  ParseStructureLikeDIE(const lldb_private::SymbolContext &sc,
-                        const lldb_private::plugin::dwarf::DWARFDIE &die,
-                        ParsedDWARFTypeAttributes &attrs);
+  lldb::TypeSP ParseStructureLikeDIE(const lldb_private::SymbolContext &sc,
+                                     const DWARFDIE &die,
+                                     ParsedDWARFTypeAttributes &attrs);
 
-  clang::Decl *
-  GetClangDeclForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);
+  clang::Decl *GetClangDeclForDIE(const DWARFDIE &die);
 
-  clang::DeclContext *
-  GetClangDeclContextForDIE(const lldb_private::plugin::dwarf::DWARFDIE &die);
+  clang::DeclContext *GetClangDeclContextForDIE(const DWARFDIE &die);
 
-  clang::DeclContext *GetClangDeclContextContainingDIE(
-      const lldb_private::plugin::dwarf::DWARFDIE &die,
-      lldb_private::plugin::dwarf::DWARFDIE *decl_ctx_die);
-  lldb_private::OptionalClangModuleID
-  GetOwningClangModule(const lldb_private::plugin::dwarf::DWARFDIE &die);
+  clang::DeclContext *GetClangDeclContextContainingDIE(const DWARFDIE &die,
+                                                       DWARFDIE *decl_ctx_die);
+  lldb_private::OptionalClangModuleID GetOwningClangModule(const DWARFDIE &die);
 
-  bool CopyUniqueClassMethodTypes(
-      const lldb_private::plugin::dwarf::DWARFDIE &src_class_die,
-      const lldb_private::plugin::dwarf::DWARFDIE &dst_class_die,
-      lldb_private::Type *class_type,
-      std::vector<lldb_private::plugin::dwarf::DWARFDIE> &failures);
+  bool CopyUniqueClassMethodTypes(const DWARFDIE &src_class_die,
+                                  const DWARFDIE &dst_class_die,
+                                  lldb_private::Type *class_type,
+                                  std::vector<DWARFDIE> &failures);
 
-  clang::DeclContext *GetCachedClangDeclContextForDIE(
-      const lldb_private::plugin::dwarf::DWARFDIE &die);
+  clang::DeclContext *GetCachedClangDeclContextForDIE(const DWARFDIE &die);
 
-  void LinkDeclContextToDIE(clang::DeclContext *decl_ctx,
-                            const lldb_private::plugin::dwarf::DWARFDIE &die);
+  void LinkDeclContextToDIE(clang::DeclContext *decl_ctx, const DWARFDIE &die);
 
-  void LinkDeclToDIE(clang::Decl *decl,
-                     const lldb_private::plugin::dwarf::DWARFDIE &die);
+  void LinkDeclToDIE(clang::Decl *decl, const DWARFDIE &die);
 
   /// If \p type_sp is valid, calculate and set its symbol context scope, and
   /// update the type list for its backing symbol file.
   ///
   /// Returns \p type_sp.
-  lldb::TypeSP UpdateSymbolContextScopeForType(
-      const lldb_private::SymbolContext &sc,
-      const lldb_private::plugin::dwarf::DWARFDIE &die, lldb::TypeSP type_sp);
+  lldb::TypeSP
+  UpdateSymbolContextScopeForType(const lldb_private::SymbolContext &sc,
+                                  const DWARFDIE &die, lldb::TypeSP type_sp);
 
   /// Follow Clang Module Skeleton CU references to find a type definition.
-  lldb::TypeSP
-  ParseTypeFromClangModule(const lldb_private::SymbolContext &sc,
-                           const lldb_private::plugin::dwarf::DWARFDIE &die,
-                           lldb_private::Log *log);
+  lldb::TypeSP ParseTypeFromClangModule(const lldb_private::SymbolContext &sc,
+                                        const DWARFDIE &die,
+                                        lldb_private::Log *log);
 
   // Return true if this type is a declaration to a type in an external
   // module.
-  lldb::ModuleSP
-  GetModuleForType(const lldb_private::plugin::dwarf::DWARFDIE &die);
+  lldb::ModuleSP GetModuleForType(const DWARFDIE &die);
 
-  void PrepareContextToReceiveMembers(
-      lldb_private::TypeSystemClang &ast,
-      clang::DeclContext *decl_ctx,
-      const lldb_private::plugin::dwarf::DWARFDIE &decl_ctx_die,
-      const lldb_private::plugin::dwarf::DWARFDIE &die,
-      const char *type_name_cstr);
+  void PrepareContextToReceiveMembers(clang::DeclContext *decl_ctx,
+                                      const DWARFDIE &decl_ctx_die,
+                                      const DWARFDIE &die,
+                                      const char *type_name_cstr);
 
   static bool classof(const DWARFASTParser *Parser) {
     return Parser->GetKind() == Kind::DWARFASTParserClang;
@@ -284,10 +265,8 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
 
   /// Parsed form of all attributes that are relevant for parsing type members.
   struct MemberAttributes {
-    explicit MemberAttributes(
-        const lldb_private::plugin::dwarf::DWARFDIE &die,
-        const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
-        lldb::ModuleSP module_sp);
+    explicit MemberAttributes(const DWARFDIE &die, const DWARFDIE &parent_die,
+                              lldb::ModuleSP module_sp);
     const char *name = nullptr;
     /// Indicates how many bits into the word (according to the host endianness)
     /// the low-order bit of the field starts. Can be negative.
@@ -334,15 +313,12 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
   /// created property.
   /// \param delayed_properties The list of delayed properties that the result
   /// will be appended to.
-  void
-  ParseObjCProperty(const lldb_private::plugin::dwarf::DWARFDIE &die,
-                    const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
-                    const lldb_private::CompilerType &class_clang_type,
-                    DelayedPropertyList &delayed_properties);
+  void ParseObjCProperty(const DWARFDIE &die, const DWARFDIE &parent_die,
+                         const lldb_private::CompilerType &class_clang_type,
+                         DelayedPropertyList &delayed_properties);
 
   void
-  ParseSingleMember(const lldb_private::plugin::dwarf::DWARFDIE &die,
-                    const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
+  ParseSingleMember(const DWARFDIE &die, const DWARFDIE &parent_die,
                     const lldb_private::CompilerType &class_clang_type,
                     lldb::AccessType default_accessibility,
                     lldb_private::ClangASTImporter::LayoutInfo &layout_info,
@@ -360,31 +336,25 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
   /// \param[in] class_clang_type The parent RecordType of the static
   ///                             member this function will create.
   void CreateStaticMemberVariable(
-      const lldb_private::plugin::dwarf::DWARFDIE &die,
-      const MemberAttributes &attrs,
+      const DWARFDIE &die, const MemberAttributes &attrs,
       const lldb_private::CompilerType &class_clang_type);
 
-  bool CompleteRecordType(const lldb_private::plugin::dwarf::DWARFDIE &die,
-                          lldb_private::Type *type,
+  bool CompleteRecordType(const DWARFDIE &die, lldb_private::Type *type,
                           lldb_private::CompilerType &clang_type);
-  bool CompleteEnumType(const lldb_private::plugin::dwarf::DWARFDIE &die,
-                        lldb_private::Type *type,
+  bool CompleteEnumType(const DWARFDIE &die, lldb_private::Type *type,
                         lldb_private::CompilerType &clang_type);
 
-  lldb::TypeSP
-  ParseTypeModifier(const lldb_private::SymbolContext &sc,
-                    const lldb_private::plugin::dwarf::DWARFDIE &die,
-                    ParsedDWARFTypeAttributes &attrs);
+  lldb::TypeSP ParseTypeModifier(const lldb_private::SymbolContext &sc,
+                                 const DWARFDIE &die,
+                                 ParsedDWARFTypeAttributes &attrs);
   lldb::TypeSP ParseEnum(const lldb_private::SymbolContext &sc,
-                         const lldb_private::plugin::dwarf::DWARFDIE &die,
-                         ParsedDWARFTypeAttributes &attrs);
-  lldb::TypeSP ParseSubroutine(const lldb_private::plugin::dwarf::DWARFDIE &die,
+                         const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs);
+  lldb::TypeSP ParseSubroutine(const DWARFDIE &die,
                                const ParsedDWARFTypeAttributes &attrs);
-  lldb::TypeSP ParseArrayType(const lldb_private::plugin::dwarf::DWARFDIE &die,
+  lldb::TypeSP ParseArrayType(const DWARFDIE &die,
                               const ParsedDWARFTypeAttributes &attrs);
-  lldb::TypeSP
-  ParsePointerToMemberType(const lldb_private::plugin::dwarf::DWARFDIE &die,
-                           const ParsedDWARFTypeAttributes &attrs);
+  lldb::TypeSP ParsePointerToMemberType(const DWARFDIE &die,
+                                        const ParsedDWARFTypeAttributes &attrs);
 
   /// Parses a DW_TAG_inheritance DIE into a base/super class.
   ///
@@ -401,8 +371,7 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
   /// \param layout_info The layout information that will be updated for C++
   /// base classes with the base offset.
   void ParseInheritance(
-      const lldb_private::plugin::dwarf::DWARFDIE &die,
-      const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
+      const DWARFDIE &die, const DWARFDIE &parent_die,
       const lldb_private::CompilerType class_clang_type,
       const lldb::AccessType default_accessibility,
       const lldb::ModuleSP &module_sp,
@@ -419,8 +388,7 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
   /// \param layout_info The layout information that will be updated for
   //   base classes with the base offset
   void
-  ParseRustVariantPart(lldb_private::plugin::dwarf::DWARFDIE &die,
-                       const lldb_private::plugin::dwarf::DWARFDIE &parent_die,
+  ParseRustVariantPart(DWARFDIE &die, const DWARFDIE &parent_die,
                        lldb_private::CompilerType &class_clang_type,
                        const lldb::AccessType default_accesibility,
                        lldb_private::ClangASTImporter::LayoutInfo &layout_info);
@@ -430,8 +398,9 @@ class DWARFASTParserClang : public lldb_private::plugin::dwarf::DWARFASTParser {
 /// Some attributes are relevant for all kinds of types (declaration), while
 /// others are only meaningful to a specific type (is_virtual)
 struct ParsedDWARFTypeAttributes {
-  explicit ParsedDWARFTypeAttributes(
-      const lldb_private::plugin::dwarf::DWARFDIE &die);
+  typedef lldb_private::plugin::dwarf::DWARFDIE DWARFDIE;
+
+  explicit ParsedDWARFTypeAttributes(const DWARFDIE &die);
 
   lldb::AccessType accessibility = lldb::eAccessNone;
   bool is_artificial = false;
@@ -448,7 +417,7 @@ struct ParsedDWARFTypeAttributes {
   const char *mangled_name = nullptr;
   lldb_private::ConstString name;
   lldb_private::Declaration decl;
-  lldb_private::plugin::dwarf::DWARFDIE object_pointer;
+  DWARFDIE object_pointer;
   lldb_private::plugin::dwarf::DWARFFormValue abstract_origin;
   lldb_private::plugin::dwarf::DWARFFormValue containing_type;
   lldb_private::plugin::dwarf::DWARFFormValue signature;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index d2f66b00c1794..10b9ae7d5ab4e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1636,14 +1636,10 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
   // type to get resolved.
   DWARFDIE dwarf_die = GetDIE(die_it->second);
   GetForwardDeclCompilerTypeToDIE().erase(die_it);
-  // The DWARFASTParser might determine if this is a declaration or not with
-  // information other than DW_AT_declaration depending on the language.
-  bool is_forward_declaration = false;
-  bool found_def_die = false;
+  Type *type = nullptr;
   if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU()))
-    found_def_die =
-        dwarf_ast->FindDefinitionDIE(dwarf_die, is_forward_declaration);
-  if (!found_def_die)
+    type = dwarf_ast->FindDefinitionTypeForDIE(dwarf_die);
+  if (!type)
     return false;
 
   die_it = GetForwardDeclCompilerTypeToDIE().find(
@@ -1653,8 +1649,6 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
     GetForwardDeclCompilerTypeToDIE().erase(die_it);
   }
 
-  Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
-
   Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
   if (log)
     GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index cc23bb86f6805..8b7b413fcf66e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -30,52 +30,52 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
               : (udt.m_byte_size < 0 || byte_size < 0 ||
                  udt.m_byte_size == byte_size) &&
                     udt.m_declaration == decl;
-      if (matching_size_declaration) {
-        // The type has the same name, and was defined on the same file and
-        // line. Now verify all of the parent DIEs match.
-        DWARFDIE parent_arg_die = die.GetParent();
-        DWARFDIE parent_pos_die = udt.m_die.GetParent();
-        bool match = true;
-        bool done = false;
-        while (!done && match && parent_arg_die && parent_pos_die) {
-          const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
-          const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
-          if (parent_arg_tag == parent_pos_tag) {
-            switch (parent_arg_tag) {
-            case DW_TAG_class_type:
-            case DW_TAG_structure_type:
-            case DW_TAG_union_type:
-            case DW_TAG_namespace: {
-              const char *parent_arg_die_name = parent_arg_die.GetName();
-              if (parent_arg_die_name ==
-                  nullptr) // Anonymous (i.e. no-name) struct
-              {
+      if (!matching_size_declaration)
+        continue;
+      // The type has the same name, and was defined on the same file and
+      // line. Now verify all of the parent DIEs match.
+      DWARFDIE parent_arg_die = die.GetParent();
+      DWARFDIE parent_pos_die = udt.m_die.GetParent();
+      bool match = true;
+      bool done = false;
+      while (!done && match && parent_arg_die && parent_pos_die) {
+        const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
+        const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
+        if (parent_arg_tag == parent_pos_tag) {
+          switch (parent_arg_tag) {
+          case DW_TAG_class_type:
+          case DW_TAG_structure_type:
+          case DW_TAG_union_type:
+          case DW_TAG_namespace: {
+            const char *parent_arg_die_name = parent_arg_die.GetName();
+            if (parent_arg_die_name ==
+                nullptr) // Anonymous (i.e. no-name) struct
+            {
+              match = false;
+            } else {
+              const char *parent_pos_die_name = parent_pos_die.GetName();
+              if (parent_pos_die_name == nullptr ||
+                  ((parent_arg_die_name != parent_pos_die_name) &&
+                   strcmp(parent_arg_die_name, parent_pos_die_name)))
                 match = false;
-              } else {
-                const char *parent_pos_die_name = parent_pos_die.GetName();
-                if (parent_pos_die_name == nullptr ||
-                    ((parent_arg_die_name != parent_pos_die_name) &&
-                     strcmp(parent_arg_die_name, parent_pos_die_name)))
-                  match = false;
-              }
-            } break;
-
-            case DW_TAG_compile_unit:
-            case DW_TAG_partial_unit:
-              done = true;
-              break;
-            default:
-              break;
             }
+          } break;
+
+          case DW_TAG_compile_unit:
+          case DW_TAG_partial_unit:
+            done = true;
+            break;
+          default:
+            break;
           }
-          parent_arg_die = parent_arg_die.GetParent();
-          parent_pos_die = parent_pos_die.GetParent();
         }
+        parent_arg_die = parent_arg_die.GetParent();
+        parent_pos_die = parent_pos_die.GetParent();
+      }
 
-        if (match) {
-          entry = udt;
-          return true;
-        }
+      if (match) {
+        entry = udt;
+        return true;
       }
     }
   }

>From 40b87f037911bf738d0e3cb670485dac33d5b079 Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Fri, 3 May 2024 16:26:19 -0400
Subject: [PATCH 5/8] address comments

---
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  | 28 +++++++++----------
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      |  2 +-
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 0db2e7984d13e..0f8beaa8363ed 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -158,21 +158,21 @@ static bool
 IsForwardDeclaration(const lldb_private::plugin::dwarf::DWARFDIE &die,
                      const ParsedDWARFTypeAttributes &attrs,
                      LanguageType cu_language) {
-  if (attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
-      !die.HasChildren() && cu_language == eLanguageTypeObjC) {
-    // Work around an issue with clang at the moment where forward
-    // declarations for objective C classes are emitted as:
-    //  DW_TAG_structure_type [2]
-    //  DW_AT_name( "ForwardObjcClass" )
-    //  DW_AT_byte_size( 0x00 )
-    //  DW_AT_decl_file( "..." )
-    //  DW_AT_decl_line( 1 )
-    //
-    // Note that there is no DW_AT_declaration and there are no children,
-    // and the byte size is zero.
+  if (attrs.is_forward_declaration)
     return true;
-  }
-  return attrs.is_forward_declaration;
+
+  // Work around an issue with clang at the moment where forward
+  // declarations for objective C classes are emitted as:
+  //  DW_TAG_structure_type [2]
+  //  DW_AT_name( "ForwardObjcClass" )
+  //  DW_AT_byte_size( 0x00 )
+  //  DW_AT_decl_file( "..." )
+  //  DW_AT_decl_line( 1 )
+  //
+  // Note that there is no DW_AT_declaration and there are no children,
+  // and the byte size is zero.
+  return attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
+      !die.HasChildren() && cu_language == eLanguageTypeObjC;
 }
 
 TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 10b9ae7d5ab4e..8b3d8b8c8903a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1632,7 +1632,7 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
   }
 
   // Once we start resolving this type, remove it from the forward
-  // declaration map in case anyone child members or other types require this
+  // declaration map in case anyone's child members or other types require this
   // type to get resolved.
   DWARFDIE dwarf_die = GetDIE(die_it->second);
   GetForwardDeclCompilerTypeToDIE().erase(die_it);

>From 0481675dcda0da45b5a66a5208bbc80f61d04b79 Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Mon, 6 May 2024 11:10:20 -0400
Subject: [PATCH 6/8] add a test

---
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  |  9 ++---
 .../delayed-definition-die-searching.test     | 40 +++++++++++++++++++
 2 files changed, 44 insertions(+), 5 deletions(-)
 create mode 100644 lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 1908a1bfffa89..7cd1626f553c3 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -154,10 +154,9 @@ static bool TagIsRecordType(dw_tag_t tag) {
   }
 }
 
-static bool
-IsForwardDeclaration(const lldb_private::plugin::dwarf::DWARFDIE &die,
-                     const ParsedDWARFTypeAttributes &attrs,
-                     LanguageType cu_language) {
+static bool IsForwardDeclaration(const DWARFDIE &die,
+                                 const ParsedDWARFTypeAttributes &attrs,
+                                 LanguageType cu_language) {
   if (attrs.is_forward_declaration)
     return true;
 
@@ -172,7 +171,7 @@ IsForwardDeclaration(const lldb_private::plugin::dwarf::DWARFDIE &die,
   // Note that there is no DW_AT_declaration and there are no children,
   // and the byte size is zero.
   return attrs.byte_size && *attrs.byte_size == 0 && attrs.name &&
-      !die.HasChildren() && cu_language == eLanguageTypeObjC;
+         !die.HasChildren() && cu_language == eLanguageTypeObjC;
 }
 
 TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
diff --git a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test
new file mode 100644
index 0000000000000..3f5293d04ccce
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test
@@ -0,0 +1,40 @@
+# Test definition DIE searching is delayed until complete type is required.
+
+# RUN: split-file %s %t
+# RUN: %clangxx_host %t/main.cpp %t/t1_def.cpp -g -gsimple-template-names -o %t.out
+# RUN: %lldb -b %t.out -s %t/lldb.cmd | FileCheck %s
+
+# CHECK:      (lldb) p v1
+# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't2'
+# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1'
+# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int'
+# CHECK-NEXT: DW_TAG_structure_type (DW_TAG_structure_type) 't2' resolving forward declaration...
+# CHECK-NEXT: (t2<t1<int> >)  {}
+# CHECK-NEXT: (lldb) p v2
+# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1'
+# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int'
+# CHECK-NEXT: DW_TAG_structure_type (DW_TAG_structure_type) 't1' resolving forward declaration...
+# CHECK-NEXT: (t1<int>)  {}
+
+#--- lldb.cmd
+log enable dwarf comp
+p v1
+p v2
+
+#--- template.h
+template<typename T>
+struct t1 {
+};
+template<typename T>
+struct t2 {
+};
+
+#--- main.cpp
+#include "template.h"
+t2<t1<int>> v1; // this CU doesn't have definition DIE for t1<int>, but only declaration DIE for it.
+int main() {
+}
+
+#--- t1_def.cpp
+#include "template.h"
+t1<int> v2; // this CU contains definition DIE for t1<int>.

>From 4f2fbfbad4b8560990266be36b394e65b3373b91 Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Tue, 7 May 2024 11:21:19 -0400
Subject: [PATCH 7/8] Use CHECK instead of CHECK-NEXT

---
 .../delayed-definition-die-searching.test     | 20 +++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test
index 3f5293d04ccce..6fe6819f66e3e 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test
+++ b/lldb/test/Shell/SymbolFile/DWARF/delayed-definition-die-searching.test
@@ -5,16 +5,16 @@
 # RUN: %lldb -b %t.out -s %t/lldb.cmd | FileCheck %s
 
 # CHECK:      (lldb) p v1
-# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't2'
-# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1'
-# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int'
-# CHECK-NEXT: DW_TAG_structure_type (DW_TAG_structure_type) 't2' resolving forward declaration...
-# CHECK-NEXT: (t2<t1<int> >)  {}
-# CHECK-NEXT: (lldb) p v2
-# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1'
-# CHECK-NEXT: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int'
-# CHECK-NEXT: DW_TAG_structure_type (DW_TAG_structure_type) 't1' resolving forward declaration...
-# CHECK-NEXT: (t1<int>)  {}
+# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't2'
+# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1'
+# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int'
+# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't2' resolving forward declaration...
+# CHECK: (t2<t1<int> >)  {}
+# CHECK: (lldb) p v2
+# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_structure_type (DW_TAG_structure_type) name = 't1'
+# CHECK: DWARFASTParserClang::ParseTypeFromDWARF{{.*}}DW_TAG_base_type (DW_TAG_base_type) name = 'int'
+# CHECK: DW_TAG_structure_type (DW_TAG_structure_type) 't1' resolving forward declaration...
+# CHECK: (t1<int>)  {}
 
 #--- lldb.cmd
 log enable dwarf comp

>From c7edf1566a68a0b361f608d84df990f576042007 Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Tue, 7 May 2024 16:58:00 -0400
Subject: [PATCH 8/8] address comments

---
 lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp   | 3 +--
 .../source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp | 5 ++---
 lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h  | 7 -------
 3 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index dcb2f62fc4dfd..5a07fd30fbf70 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1650,8 +1650,7 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
     GetForwardDeclCompilerTypeToDIE().erase(die_it);
   }
 
-  Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion);
-  if (log)
+  if (Log *log = GetLog(DWARFLog::DebugInfo | DWARFLog::TypeCompletion))
     GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
         log, "{0:x8}: {1} ({2}) '{3}' resolving forward declaration...",
         dwarf_die.GetID(), DW_TAG_value_to_name(dwarf_die.Tag()),
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 8b7b413fcf66e..a156c13314bbb 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -48,9 +48,8 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
           case DW_TAG_union_type:
           case DW_TAG_namespace: {
             const char *parent_arg_die_name = parent_arg_die.GetName();
-            if (parent_arg_die_name ==
-                nullptr) // Anonymous (i.e. no-name) struct
-            {
+            if (parent_arg_die_name == nullptr) {
+              // Anonymous (i.e. no-name) struct
               match = false;
             } else {
               const char *parent_pos_die_name = parent_pos_die.GetName();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
index 94619953d07ac..f2ff42ae83d50 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
@@ -23,13 +23,6 @@ class UniqueDWARFASTType {
   // Constructors and Destructors
   UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {}
 
-  UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die,
-                     const Declaration &decl, int32_t byte_size,
-                     bool is_forward_declaration)
-      : m_type_sp(type_sp), m_die(die), m_declaration(decl),
-        m_byte_size(byte_size),
-        m_is_forward_declaration(is_forward_declaration) {}
-
   UniqueDWARFASTType(const UniqueDWARFASTType &rhs)
       : m_type_sp(rhs.m_type_sp), m_die(rhs.m_die),
         m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size),



More information about the lldb-commits mailing list