[Lldb-commits] [lldb] r373927 - [DWARFASTParserClang] Factor out structure-like type parsing, NFC

Vedant Kumar via lldb-commits lldb-commits at lists.llvm.org
Mon Oct 7 10:22:53 PDT 2019


Author: vedantk
Date: Mon Oct  7 10:22:53 2019
New Revision: 373927

URL: http://llvm.org/viewvc/llvm-project?rev=373927&view=rev
Log:
[DWARFASTParserClang] Factor out structure-like type parsing, NFC

Split out the logic to parse structure-like types into a separate
function, in an attempt to reduce the complexity of ParseTypeFromDWARF.

Inspired by discussion in https://reviews.llvm.org/D68130.

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

Modified:
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h?rev=373927&r1=373926&r2=373927&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h Mon Oct  7 10:22:53 2019
@@ -28,7 +28,6 @@ public:
 
   virtual lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
                                           const DWARFDIE &die,
-                                          lldb_private::Log *log,
                                           bool *type_is_new_ptr) = 0;
 
   virtual lldb_private::Function *

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp?rev=373927&r1=373926&r2=373927&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp Mon Oct  7 10:22:53 2019
@@ -9,7 +9,6 @@
 #include <stdlib.h>
 
 #include "DWARFASTParserClang.h"
-#include "DWARFDIE.h"
 #include "DWARFDebugInfo.h"
 #include "DWARFDeclContext.h"
 #include "DWARFDefines.h"
@@ -232,42 +231,7 @@ static void CompleteExternalTagDeclType(
   }
 }
 
-namespace {
-/// Parsed form of all attributes that are relevant for type reconstruction.
-/// Some attributes are relevant for all kinds of types (declaration), while
-/// others are only meaningful to a specific type (is_virtual)
-struct ParsedTypeAttributes {
-  explicit ParsedTypeAttributes(const DWARFDIE &die);
-
-  AccessType accessibility = eAccessNone;
-  bool is_artificial = false;
-  bool is_complete_objc_class = false;
-  bool is_explicit = false;
-  bool is_forward_declaration = false;
-  bool is_inline = false;
-  bool is_scoped_enum = false;
-  bool is_vector = false;
-  bool is_virtual = false;
-  clang::StorageClass storage = clang::SC_None;
-  const char *mangled_name = nullptr;
-  ConstString name;
-  Declaration decl;
-  DWARFDIE object_pointer;
-  DWARFFormValue abstract_origin;
-  DWARFFormValue containing_type;
-  DWARFFormValue signature;
-  DWARFFormValue specification;
-  DWARFFormValue type;
-  LanguageType class_language = eLanguageTypeUnknown;
-  llvm::Optional<uint64_t> byte_size;
-  size_t calling_convention = llvm::dwarf::DW_CC_normal;
-  uint32_t bit_stride = 0;
-  uint32_t byte_stride = 0;
-  uint32_t encoding = 0;
-};
-} // namespace
-
-ParsedTypeAttributes::ParsedTypeAttributes(const DWARFDIE &die) {
+ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
   DWARFAttributes attributes;
   size_t num_attributes = die.GetAttributes(attributes);
   for (size_t i = 0; i < num_attributes; ++i) {
@@ -394,13 +358,17 @@ static std::string GetUnitName(const DWA
 }
 
 TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
-                                               const DWARFDIE &die, Log *log,
+                                               const DWARFDIE &die,
                                                bool *type_is_new_ptr) {
   if (type_is_new_ptr)
     *type_is_new_ptr = false;
 
   if (!die)
     return nullptr;
+
+  Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
+                                        DWARF_LOG_LOOKUPS));
+
   SymbolFileDWARF *dwarf = die.GetDWARF();
   if (log) {
     DWARFDIE context_die;
@@ -424,11 +392,11 @@ TypeSP DWARFASTParserClang::ParseTypeFro
   // Set a bit that lets us know that we are currently parsing this
   dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
 
-  ParsedTypeAttributes attrs(die);
+  ParsedDWARFTypeAttributes attrs(die);
 
   if (DWARFDIE signature_die = attrs.signature.Reference()) {
     if (TypeSP type_sp =
-            ParseTypeFromDWARF(sc, signature_die, log, type_is_new_ptr)) {
+            ParseTypeFromDWARF(sc, signature_die, type_is_new_ptr)) {
       dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
       if (clang::DeclContext *decl_ctx =
               GetCachedClangDeclContextForDIE(signature_die))
@@ -438,7 +406,6 @@ TypeSP DWARFASTParserClang::ParseTypeFro
     return nullptr;
   }
 
-  TypeList &type_list = dwarf->GetTypeList();
   if (type_is_new_ptr)
     *type_is_new_ptr = true;
 
@@ -566,7 +533,7 @@ TypeSP DWARFASTParserClang::ParseTypeFro
 
                 bool function_type_is_new_pointer;
                 TypeSP lldb_function_type_sp = ParseTypeFromDWARF(
-                    sc, function_type, log, &function_type_is_new_pointer);
+                    sc, function_type, &function_type_is_new_pointer);
 
                 if (lldb_function_type_sp) {
                   clang_type = m_ast.CreateBlockPointerType(
@@ -664,372 +631,11 @@ TypeSP DWARFASTParserClang::ParseTypeFro
   case DW_TAG_structure_type:
   case DW_TAG_union_type:
   case DW_TAG_class_type: {
-    // UniqueDWARFASTType is large, so don't create a local variables on
-    // the stack, put it on the heap. This function is often called
-    // recursively and clang isn't good and sharing the stack space for
-    // variables in different blocks.
-    std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_up(
-        new UniqueDWARFASTType());
-
-    ConstString unique_typename(attrs.name);
-    Declaration unique_decl(attrs.decl);
-
-    if (attrs.name) {
-      if (Language::LanguageIsCPlusPlus(cu_language)) {
-        // For C++, we rely solely upon the one definition rule that says
-        // only one thing can exist at a given decl context. We ignore the
-        // file and line that things are declared on.
-        std::string qualified_name;
-        if (die.GetQualifiedName(qualified_name))
-          unique_typename = ConstString(qualified_name);
-        unique_decl.Clear();
-      }
-
-      if (dwarf->GetUniqueDWARFASTTypeMap().Find(
-              unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-1),
-              *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);
-          return type_sp;
-        }
-      }
-    }
-
-    DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
-                 DW_TAG_value_to_name(tag), type_name_cstr);
-
-    int tag_decl_kind = -1;
-    AccessType default_accessibility = eAccessNone;
-    if (tag == DW_TAG_structure_type) {
-      tag_decl_kind = clang::TTK_Struct;
-      default_accessibility = eAccessPublic;
-    } else if (tag == DW_TAG_union_type) {
-      tag_decl_kind = clang::TTK_Union;
-      default_accessibility = eAccessPublic;
-    } else if (tag == DW_TAG_class_type) {
-      tag_decl_kind = clang::TTK_Class;
-      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.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(%p) - 0x%8.8x: %s type \"%s\" is an "
-                "incomplete objc type, complete type is 0x%8.8" PRIx64,
-                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(%p) - 0x%8.8x: %s type \"%s\" 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 DWO module and if so, track down that
-      // type.
-      type_sp = ParseTypeFromDWO(die, log);
-      if (type_sp)
-        return type_sp;
-
-      DWARFDeclContext die_decl_ctx;
-      die.GetDWARFDeclContext(die_decl_ctx);
-
-      // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die,
-      // type_name_const_str);
-      type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
-
-      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_decl_ctx);
-        }
-      }
-
-      if (type_sp) {
-        if (log) {
-          dwarf->GetObjectFile()->GetModule()->LogMessage(
-              log,
-              "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a "
-              "forward declaration, complete type is 0x%8.8" PRIx64,
-              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);
-    bool clang_type_was_created = false;
-    clang_type.SetCompilerType(
-        &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
-    if (!clang_type) {
-      clang::DeclContext *decl_ctx =
-          GetClangDeclContextContainingDIE(die, nullptr);
-
-      // If your decl context is a record that was imported from another
-      // AST context (in the gmodules case), we need to make sure the type
-      // backing the Decl is complete before adding children to it. This is
-      // not an issue in the non-gmodules case because the debug info will
-      // always contain a full definition of parent types in that case.
-      CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die,
-                                  attrs.name.GetCString());
-
-      if (attrs.accessibility == eAccessNone && decl_ctx) {
-        // Check the decl context that contains this class/struct/union. If
-        // it is a class we must give it an accessibility.
-        const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind();
-        if (DeclKindIsCXXClass(containing_decl_kind))
-          attrs.accessibility = default_accessibility;
-      }
-
-      ClangASTMetadata metadata;
-      metadata.SetUserID(die.GetID());
-      metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die));
-
-      if (attrs.name.GetStringRef().contains('<')) {
-        ClangASTContext::TemplateParameterInfos template_param_infos;
-        if (ParseTemplateParameterInfos(die, template_param_infos)) {
-          clang::ClassTemplateDecl *class_template_decl =
-              m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility,
-                                           attrs.name.GetCString(),
-                                           tag_decl_kind, template_param_infos);
-          if (!class_template_decl) {
-            if (log) {
-              dwarf->GetObjectFile()->GetModule()->LogMessage(
-                  log,
-                  "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" "
-                  "clang::ClassTemplateDecl failed to return a decl.",
-                  static_cast<void *>(this), die.GetOffset(),
-                  DW_TAG_value_to_name(tag), attrs.name.GetCString());
-            }
-            return TypeSP();
-          }
-
-          clang::ClassTemplateSpecializationDecl *class_specialization_decl =
-              m_ast.CreateClassTemplateSpecializationDecl(
-                  decl_ctx, class_template_decl, 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;
-        clang_type = m_ast.CreateRecordType(
-            decl_ctx, attrs.accessibility, attrs.name.GetCString(),
-            tag_decl_kind, attrs.class_language, &metadata);
-      }
-    }
-
-    // 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.
-    LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die);
-    type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name,
-                                     attrs.byte_size, nullptr, LLDB_INVALID_UID,
-                                     Type::eEncodingIsUID, &attrs.decl, clang_type,
-                                     Type::eResolveStateForward);
-
-    type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class);
-
-    // Add our type to the unique type map so we don't end up creating many
-    // copies of the same type over and over in the ASTContext for our
-    // module
-    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.getValueOr(0);
-    dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename,
-                                             *unique_ast_entry_up);
-
-    if (attrs.is_forward_declaration && die.HasChildren()) {
-      // Check to see if the DIE actually has a definition, some version of
-      // GCC will
-      // emit DIEs with DW_AT_declaration set to true, but yet still have
-      // subprogram, members, or inheritance, so we can't trust it
-      DWARFDIE child_die = die.GetFirstChild();
-      while (child_die) {
-        switch (child_die.Tag()) {
-        case DW_TAG_inheritance:
-        case DW_TAG_subprogram:
-        case DW_TAG_member:
-        case DW_TAG_APPLE_property:
-        case DW_TAG_class_type:
-        case DW_TAG_structure_type:
-        case DW_TAG_enumeration_type:
-        case DW_TAG_typedef:
-        case DW_TAG_union_type:
-          child_die.Clear();
-          attrs.is_forward_declaration = false;
-          break;
-        default:
-          child_die = child_die.GetSibling();
-          break;
-        }
-      }
-    }
-
-    if (!attrs.is_forward_declaration) {
-      // Always start the definition for a class type so that if the class
-      // has child classes or types that require the class to be created
-      // for use as their decl contexts the class will be ready to accept
-      // these child definitions.
-      if (!die.HasChildren()) {
-        // No children for this struct/union/class, lets finish it
-        if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
-          ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
-        } else {
-          dwarf->GetObjectFile()->GetModule()->ReportError(
-              "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its "
-              "definition.\nPlease file a bug and attach the file at the "
-              "start of this error message",
-              die.GetOffset(), attrs.name.GetCString());
-        }
-
-        if (tag == DW_TAG_structure_type) // this only applies in C
-        {
-          clang::RecordDecl *record_decl =
-              ClangASTContext::GetAsRecordDecl(clang_type);
-
-          if (record_decl) {
-            GetClangASTImporter().InsertRecordDecl(
-                record_decl, ClangASTImporter::LayoutInfo());
-          }
-        }
-      } 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)
-          ClangASTContext::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->GetForwardDeclClangTypeToDie().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->GetForwardDeclDieToClangType()[die.GetDIE()] =
-            clang_type.GetOpaqueQualType();
-        dwarf->GetForwardDeclClangTypeToDie()
-            [ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] =
-            die.GetID();
-        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
-    // value is pass by reference, so we ignore that attribute if set.
-    if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) {
-      clang::CXXRecordDecl *record_decl =
-          m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
-      if (record_decl && record_decl->getDefinition()) {
-        record_decl->setHasTrivialSpecialMemberForCall();
-      }
-    }
-
-    if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) {
-      clang::CXXRecordDecl *record_decl =
-          m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
-      if (record_decl)
-        record_decl->setArgPassingRestrictions(
-            clang::RecordDecl::APK_CannotPassInRegs);
-    }
-
-  } break;
+    assert((!type_sp && !clang_type) &&
+           "Did not expect partially computed structure-like type");
+    TypeSP struct_like_type_sp = ParseStructureLikeDIE(die, attrs);
+    return UpdateSymbolContextScopeForType(sc, die, struct_like_type_sp);
+  }
 
   case DW_TAG_enumeration_type: {
     if (attrs.is_forward_declaration) {
@@ -1656,31 +1262,418 @@ TypeSP DWARFASTParserClang::ParseTypeFro
     break;
   }
 
-  if (type_sp.get()) {
-    DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
-    dw_tag_t sc_parent_tag = sc_parent_die.Tag();
-
-    SymbolContextScope *symbol_context_scope = NULL;
-    if (sc_parent_tag == DW_TAG_compile_unit ||
-        sc_parent_tag == DW_TAG_partial_unit) {
-      symbol_context_scope = sc.comp_unit;
-    } else if (sc.function != NULL && sc_parent_die) {
-      symbol_context_scope =
-          sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
-      if (symbol_context_scope == NULL)
-        symbol_context_scope = sc.function;
-    } else
-      symbol_context_scope = sc.module_sp.get();
-
-    if (symbol_context_scope != NULL) {
-      type_sp->SetSymbolContextScope(symbol_context_scope);
-    }
-
-    // We are ready to put this type into the uniqued list up at the module
-    // level
-    type_list.Insert(type_sp);
+  // TODO: We should consider making the switch above exhaustive to simplify
+  // control flow in ParseTypeFromDWARF. Then, we could simply replace this
+  // return statement with a call to llvm_unreachable.
+  return UpdateSymbolContextScopeForType(sc, die, type_sp);
+}
+
+TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(
+    const SymbolContext &sc, const DWARFDIE &die, TypeSP type_sp) {
+  if (!type_sp)
+    return type_sp;
 
-    dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+  SymbolFileDWARF *dwarf = die.GetDWARF();
+  TypeList &type_list = dwarf->GetTypeList();
+  DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
+  dw_tag_t sc_parent_tag = sc_parent_die.Tag();
+
+  SymbolContextScope *symbol_context_scope = NULL;
+  if (sc_parent_tag == DW_TAG_compile_unit ||
+      sc_parent_tag == DW_TAG_partial_unit) {
+    symbol_context_scope = sc.comp_unit;
+  } else if (sc.function != NULL && sc_parent_die) {
+    symbol_context_scope =
+        sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
+    if (symbol_context_scope == NULL)
+      symbol_context_scope = sc.function;
+  } else {
+    symbol_context_scope = sc.module_sp.get();
+  }
+
+  if (symbol_context_scope != NULL)
+    type_sp->SetSymbolContextScope(symbol_context_scope);
+
+  // We are ready to put this type into the uniqued list up at the module
+  // level.
+  type_list.Insert(type_sp);
+
+  dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+  return type_sp;
+}
+
+TypeSP
+DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
+                                           ParsedDWARFTypeAttributes &attrs) {
+  TypeSP type_sp;
+  CompilerType clang_type;
+  const dw_tag_t tag = die.Tag();
+  SymbolFileDWARF *dwarf = die.GetDWARF();
+  LanguageType cu_language = die.GetLanguage();
+  Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_TYPE_COMPLETION |
+                                          DWARF_LOG_LOOKUPS);
+
+  // UniqueDWARFASTType is large, so don't create a local variables on the
+  // stack, put it on the heap. This function is often called recursively and
+  // clang isn't good at sharing the stack space for variables in different
+  // blocks.
+  auto unique_ast_entry_up = std::make_unique<UniqueDWARFASTType>();
+
+  ConstString unique_typename(attrs.name);
+  Declaration unique_decl(attrs.decl);
+
+  if (attrs.name) {
+    if (Language::LanguageIsCPlusPlus(cu_language)) {
+      // For C++, we rely solely upon the one definition rule that says
+      // only one thing can exist at a given decl context. We ignore the
+      // file and line that things are declared on.
+      std::string qualified_name;
+      if (die.GetQualifiedName(qualified_name))
+        unique_typename = ConstString(qualified_name);
+      unique_decl.Clear();
+    }
+
+    if (dwarf->GetUniqueDWARFASTTypeMap().Find(
+            unique_typename, die, unique_decl, attrs.byte_size.getValueOr(-1),
+            *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);
+        return type_sp;
+      }
+    }
+  }
+
+  DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
+               DW_TAG_value_to_name(tag), type_name_cstr);
+
+  int tag_decl_kind = -1;
+  AccessType default_accessibility = eAccessNone;
+  if (tag == DW_TAG_structure_type) {
+    tag_decl_kind = clang::TTK_Struct;
+    default_accessibility = eAccessPublic;
+  } else if (tag == DW_TAG_union_type) {
+    tag_decl_kind = clang::TTK_Union;
+    default_accessibility = eAccessPublic;
+  } else if (tag == DW_TAG_class_type) {
+    tag_decl_kind = clang::TTK_Class;
+    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.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(%p) - 0x%8.8x: %s type \"%s\" is an "
+              "incomplete objc type, complete type is 0x%8.8" PRIx64,
+              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(%p) - 0x%8.8x: %s type \"%s\" 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 DWO module and if so, track down that
+    // type.
+    type_sp = ParseTypeFromDWO(die, log);
+    if (type_sp)
+      return type_sp;
+
+    DWARFDeclContext die_decl_ctx;
+    die.GetDWARFDeclContext(die_decl_ctx);
+
+    // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die,
+    // type_name_const_str);
+    type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
+
+    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_decl_ctx);
+      }
+    }
+
+    if (type_sp) {
+      if (log) {
+        dwarf->GetObjectFile()->GetModule()->LogMessage(
+            log,
+            "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a "
+            "forward declaration, complete type is 0x%8.8" PRIx64,
+            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);
+  bool clang_type_was_created = false;
+  clang_type.SetCompilerType(
+      &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
+  if (!clang_type) {
+    clang::DeclContext *decl_ctx =
+        GetClangDeclContextContainingDIE(die, nullptr);
+
+    // If your decl context is a record that was imported from another
+    // AST context (in the gmodules case), we need to make sure the type
+    // backing the Decl is complete before adding children to it. This is
+    // not an issue in the non-gmodules case because the debug info will
+    // always contain a full definition of parent types in that case.
+    CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die,
+                                attrs.name.GetCString());
+
+    if (attrs.accessibility == eAccessNone && decl_ctx) {
+      // Check the decl context that contains this class/struct/union. If
+      // it is a class we must give it an accessibility.
+      const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind();
+      if (DeclKindIsCXXClass(containing_decl_kind))
+        attrs.accessibility = default_accessibility;
+    }
+
+    ClangASTMetadata metadata;
+    metadata.SetUserID(die.GetID());
+    metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die));
+
+    if (attrs.name.GetStringRef().contains('<')) {
+      ClangASTContext::TemplateParameterInfos template_param_infos;
+      if (ParseTemplateParameterInfos(die, template_param_infos)) {
+        clang::ClassTemplateDecl *class_template_decl =
+            m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility,
+                                         attrs.name.GetCString(), tag_decl_kind,
+                                         template_param_infos);
+        if (!class_template_decl) {
+          if (log) {
+            dwarf->GetObjectFile()->GetModule()->LogMessage(
+                log,
+                "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" "
+                "clang::ClassTemplateDecl failed to return a decl.",
+                static_cast<void *>(this), die.GetOffset(),
+                DW_TAG_value_to_name(tag), attrs.name.GetCString());
+          }
+          return TypeSP();
+        }
+
+        clang::ClassTemplateSpecializationDecl *class_specialization_decl =
+            m_ast.CreateClassTemplateSpecializationDecl(
+                decl_ctx, class_template_decl, 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;
+      clang_type = m_ast.CreateRecordType(
+          decl_ctx, attrs.accessibility, attrs.name.GetCString(), tag_decl_kind,
+          attrs.class_language, &metadata);
+    }
+  }
+
+  // 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.
+  LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die);
+  type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name,
+                                   attrs.byte_size, nullptr, LLDB_INVALID_UID,
+                                   Type::eEncodingIsUID, &attrs.decl,
+                                   clang_type, Type::eResolveStateForward);
+
+  type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class);
+
+  // Add our type to the unique type map so we don't end up creating many
+  // copies of the same type over and over in the ASTContext for our
+  // module
+  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.getValueOr(0);
+  dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename,
+                                           *unique_ast_entry_up);
+
+  if (attrs.is_forward_declaration && die.HasChildren()) {
+    // Check to see if the DIE actually has a definition, some version of
+    // GCC will
+    // emit DIEs with DW_AT_declaration set to true, but yet still have
+    // subprogram, members, or inheritance, so we can't trust it
+    DWARFDIE child_die = die.GetFirstChild();
+    while (child_die) {
+      switch (child_die.Tag()) {
+      case DW_TAG_inheritance:
+      case DW_TAG_subprogram:
+      case DW_TAG_member:
+      case DW_TAG_APPLE_property:
+      case DW_TAG_class_type:
+      case DW_TAG_structure_type:
+      case DW_TAG_enumeration_type:
+      case DW_TAG_typedef:
+      case DW_TAG_union_type:
+        child_die.Clear();
+        attrs.is_forward_declaration = false;
+        break;
+      default:
+        child_die = child_die.GetSibling();
+        break;
+      }
+    }
+  }
+
+  if (!attrs.is_forward_declaration) {
+    // Always start the definition for a class type so that if the class
+    // has child classes or types that require the class to be created
+    // for use as their decl contexts the class will be ready to accept
+    // these child definitions.
+    if (!die.HasChildren()) {
+      // No children for this struct/union/class, lets finish it
+      if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
+        ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
+      } else {
+        dwarf->GetObjectFile()->GetModule()->ReportError(
+            "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its "
+            "definition.\nPlease file a bug and attach the file at the "
+            "start of this error message",
+            die.GetOffset(), attrs.name.GetCString());
+      }
+
+      if (tag == DW_TAG_structure_type) // this only applies in C
+      {
+        clang::RecordDecl *record_decl =
+            ClangASTContext::GetAsRecordDecl(clang_type);
+
+        if (record_decl) {
+          GetClangASTImporter().InsertRecordDecl(
+              record_decl, ClangASTImporter::LayoutInfo());
+        }
+      }
+    } 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)
+        ClangASTContext::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->GetForwardDeclClangTypeToDie().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->GetForwardDeclDieToClangType()[die.GetDIE()] =
+          clang_type.GetOpaqueQualType();
+      dwarf->GetForwardDeclClangTypeToDie()
+          [ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] =
+          die.GetID();
+      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
+  // value is pass by reference, so we ignore that attribute if set.
+  if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) {
+    clang::CXXRecordDecl *record_decl =
+        m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
+    if (record_decl && record_decl->getDefinition()) {
+      record_decl->setHasTrivialSpecialMemberForCall();
+    }
+  }
+
+  if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) {
+    clang::CXXRecordDecl *record_decl =
+        m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
+    if (record_decl)
+      record_decl->setArgPassingRestrictions(
+          clang::RecordDecl::APK_CannotPassInRegs);
   }
   return type_sp;
 }

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h?rev=373927&r1=373926&r2=373927&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h Mon Oct  7 10:22:53 2019
@@ -15,7 +15,10 @@
 #include "llvm/ADT/SmallVector.h"
 
 #include "DWARFASTParser.h"
+#include "DWARFDIE.h"
 #include "DWARFDefines.h"
+#include "DWARFFormValue.h"
+#include "LogChannelDWARF.h"
 #include "lldb/Core/ClangForward.h"
 #include "lldb/Core/PluginInterface.h"
 #include "lldb/Symbol/ClangASTContext.h"
@@ -29,6 +32,8 @@ class CompileUnit;
 class DWARFDebugInfoEntry;
 class SymbolFileDWARF;
 
+struct ParsedDWARFTypeAttributes;
+
 class DWARFASTParserClang : public DWARFASTParser {
 public:
   DWARFASTParserClang(lldb_private::ClangASTContext &ast);
@@ -37,7 +42,7 @@ public:
 
   // DWARFASTParser interface.
   lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
-                                  const DWARFDIE &die, lldb_private::Log *log,
+                                  const DWARFDIE &die,
                                   bool *type_is_new_ptr) override;
 
   lldb_private::Function *
@@ -122,6 +127,10 @@ protected:
                                bool is_signed, uint32_t enumerator_byte_size,
                                const DWARFDIE &parent_die);
 
+  /// Parse a structure, class, or union type DIE.
+  lldb::TypeSP ParseStructureLikeDIE(const DWARFDIE &die,
+                                     ParsedDWARFTypeAttributes &attrs);
+
   lldb_private::Type *GetTypeForDIE(const DWARFDIE &die);
 
   clang::Decl *GetClangDeclForDIE(const DWARFDIE &die);
@@ -142,6 +151,14 @@ protected:
 
   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 DWARFDIE &die, lldb::TypeSP type_sp);
+
   lldb::TypeSP ParseTypeFromDWO(const DWARFDIE &die, lldb_private::Log *log);
 
   // Return true if this type is a declaration to a type in an external
@@ -149,4 +166,37 @@ protected:
   lldb::ModuleSP GetModuleForType(const DWARFDIE &die);
 };
 
+/// Parsed form of all attributes that are relevant for type reconstruction.
+/// 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 DWARFDIE &die);
+
+  lldb::AccessType accessibility = lldb::eAccessNone;
+  bool is_artificial = false;
+  bool is_complete_objc_class = false;
+  bool is_explicit = false;
+  bool is_forward_declaration = false;
+  bool is_inline = false;
+  bool is_scoped_enum = false;
+  bool is_vector = false;
+  bool is_virtual = false;
+  clang::StorageClass storage = clang::SC_None;
+  const char *mangled_name = nullptr;
+  lldb_private::ConstString name;
+  lldb_private::Declaration decl;
+  DWARFDIE object_pointer;
+  DWARFFormValue abstract_origin;
+  DWARFFormValue containing_type;
+  DWARFFormValue signature;
+  DWARFFormValue specification;
+  DWARFFormValue type;
+  lldb::LanguageType class_language = lldb::eLanguageTypeUnknown;
+  llvm::Optional<uint64_t> byte_size;
+  size_t calling_convention = llvm::dwarf::DW_CC_normal;
+  uint32_t bit_stride = 0;
+  uint32_t byte_stride = 0;
+  uint32_t encoding = 0;
+};
+
 #endif // SymbolFileDWARF_DWARFASTParserClang_h_

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=373927&r1=373926&r2=373927&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Mon Oct  7 10:22:53 2019
@@ -3001,8 +3001,7 @@ TypeSP SymbolFileDWARF::ParseType(const
   if (!dwarf_ast)
     return {};
 
-  Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
-  TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, log, type_is_new_ptr);
+  TypeSP type_sp = dwarf_ast->ParseTypeFromDWARF(sc, die, type_is_new_ptr);
   if (type_sp) {
     GetTypeList().Insert(type_sp);
 




More information about the lldb-commits mailing list