//===-- DWARFASTParserClang.cpp ---------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include <stdlib.h>

#include "DWARFASTParserClang.h"
#include "DWARFDebugInfo.h"
#include "DWARFDeclContext.h"
#include "DWARFDefines.h"
#include "SymbolFileDWARF.h"
#include "SymbolFileDWARFDwo.h"
#include "SymbolFileDWARFDebugMap.h"
#include "UniqueDWARFASTType.h"

#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/TypeMap.h"
#include "lldb/Target/Language.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"

#include <map>
#include <memory>
#include <vector>

//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN

#ifdef ENABLE_DEBUG_PRINTF
#include <stdio.h>
#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
#endif

using namespace lldb;
using namespace lldb_private;
DWARFASTParserClang::DWARFASTParserClang(ClangASTContext &ast)
    : m_ast(ast), m_die_to_decl_ctx(), m_decl_ctx_to_die() {}

DWARFASTParserClang::~DWARFASTParserClang() {}

static AccessType DW_ACCESS_to_AccessType(uint32_t dwarf_accessibility) {
  switch (dwarf_accessibility) {
  case DW_ACCESS_public:
    return eAccessPublic;
  case DW_ACCESS_private:
    return eAccessPrivate;
  case DW_ACCESS_protected:
    return eAccessProtected;
  default:
    break;
  }
  return eAccessNone;
}

static bool DeclKindIsCXXClass(clang::Decl::Kind decl_kind) {
  switch (decl_kind) {
  case clang::Decl::CXXRecord:
  case clang::Decl::ClassTemplateSpecialization:
    return true;
  default:
    break;
  }
  return false;
}

struct BitfieldInfo {
  uint64_t bit_size;
  uint64_t bit_offset;

  BitfieldInfo()
      : bit_size(LLDB_INVALID_ADDRESS), bit_offset(LLDB_INVALID_ADDRESS) {}

  void Clear() {
    bit_size = LLDB_INVALID_ADDRESS;
    bit_offset = LLDB_INVALID_ADDRESS;
  }

  bool IsValid() const {
    return (bit_size != LLDB_INVALID_ADDRESS) &&
           (bit_offset != LLDB_INVALID_ADDRESS);
  }

  bool NextBitfieldOffsetIsValid(const uint64_t next_bit_offset) const {
    if (IsValid()) {
      // This bitfield info is valid, so any subsequent bitfields must not
      // overlap and must be at a higher bit offset than any previous bitfield
      // + size.
      return (bit_size + bit_offset) <= next_bit_offset;
    } else {
      // If the this BitfieldInfo is not valid, then any offset isOK
      return true;
    }
  }
};

ClangASTImporter &DWARFASTParserClang::GetClangASTImporter() {
  if (!m_clang_ast_importer_up) {
    m_clang_ast_importer_up.reset(new ClangASTImporter);
  }
  return *m_clang_ast_importer_up;
}

/// Detect a forward declaration that is nested in a DW_TAG_module.
static bool IsClangModuleFwdDecl(const DWARFDIE &Die) {
  if (!Die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
    return false;
  auto Parent = Die.GetParent();
  while (Parent.IsValid()) {
    if (Parent.Tag() == DW_TAG_module)
      return true;
    Parent = Parent.GetParent();
  }
  return false;
}

TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) {
  ModuleSP dwo_module_sp = die.GetContainingDWOModule();
  if (!dwo_module_sp)
    return TypeSP();

  // If this type comes from a Clang module, look in the DWARF section
  // of the pcm file in the module cache. Clang generates DWO skeleton
  // units as breadcrumbs to find them.
  llvm::SmallVector<CompilerContext, 4> decl_context;
  die.GetDeclContext(decl_context);
  TypeMap dwo_types;

  // The type in the Clang module must have the same language as the current CU.
  LanguageSet languages;
  languages.Insert(die.GetCU()->GetLanguageType());
  dwo_module_sp->GetSymbolFile()->FindTypes(decl_context, languages, dwo_types);
  if (dwo_types.Empty()) {
    if (!IsClangModuleFwdDecl(die))
      return TypeSP();

    // Since this type is defined in one of the Clang modules imported
    // by this symbol file, search all of them.
    auto &sym_file = die.GetCU()->GetSymbolFileDWARF();
    for (const auto &name_module : sym_file.getExternalTypeModules()) {
      if (!name_module.second)
        continue;
      name_module.second->GetSymbolFile()->FindTypes(decl_context,
                                                     languages, dwo_types);
      if (dwo_types.GetSize())
        break;
    }
  }

  if (dwo_types.GetSize() != 1)
    return TypeSP();

  // We found a real definition for this type in the Clang module, so lets use
  // it and cache the fact that we found a complete type for this die.
  TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
  if (!dwo_type_sp)
    return TypeSP();

  lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType();

  lldb_private::CompilerType type =
      GetClangASTImporter().CopyType(m_ast, dwo_type);

  if (!type)
    return TypeSP();

  SymbolFileDWARF *dwarf = die.GetDWARF();
  TypeSP type_sp(new Type(
      die.GetID(), dwarf, dwo_type_sp->GetName(), dwo_type_sp->GetByteSize(),
      nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid,
      &dwo_type_sp->GetDeclaration(), type, Type::eResolveStateForward));

  dwarf->GetTypeList().Insert(type_sp);
  dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
  clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type);
  if (tag_decl)
    LinkDeclContextToDIE(tag_decl, die);
  else {
    clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die);
    if (defn_decl_ctx)
      LinkDeclContextToDIE(defn_decl_ctx, die);
  }

  return type_sp;
}

static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer,
                                        clang::DeclContext *decl_ctx,
                                        DWARFDIE die,
                                        const char *type_name_cstr) {
  auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);
  if (!tag_decl_ctx)
    return;

  // If this type was not imported from an external AST, there's nothing to do.
  CompilerType type = ClangASTContext::GetTypeForDecl(tag_decl_ctx);
  if (!type || !ast_importer.CanImport(type))
    return;

  auto qual_type = ClangUtil::GetQualType(type);
  if (!ast_importer.RequireCompleteType(qual_type)) {
    die.GetDWARF()->GetObjectFile()->GetModule()->ReportError(
        "Unable to complete the Decl context for DIE '%s' at offset "
        "0x%8.8x.\nPlease file a bug report.",
        type_name_cstr ? type_name_cstr : "", die.GetOffset());
    // We need to make the type look complete otherwise, we might crash in
    // Clang when adding children.
    if (ClangASTContext::StartTagDeclarationDefinition(type))
      ClangASTContext::CompleteTagDeclarationDefinition(type);
  }
}

ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
  DWARFAttributes attributes;
  size_t num_attributes = die.GetAttributes(attributes);
  for (size_t i = 0; i < num_attributes; ++i) {
    dw_attr_t attr = attributes.AttributeAtIndex(i);
    DWARFFormValue form_value;
    if (!attributes.ExtractFormValueAtIndex(i, form_value))
      continue;
    switch (attr) {
    case DW_AT_abstract_origin:
      abstract_origin = form_value;
      break;

    case DW_AT_accessibility:
      accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
      break;

    case DW_AT_artificial:
      is_artificial = form_value.Boolean();
      break;

    case DW_AT_bit_stride:
      bit_stride = form_value.Unsigned();
      break;

    case DW_AT_byte_size:
      byte_size = form_value.Unsigned();
      break;

    case DW_AT_byte_stride:
      byte_stride = form_value.Unsigned();
      break;

    case DW_AT_calling_convention:
      calling_convention = form_value.Unsigned();
      break;

    case DW_AT_containing_type:
      containing_type = form_value;
      break;

    case DW_AT_decl_file:
      decl.SetFile(die.GetCU()->GetFile(form_value.Unsigned()));
      break;
    case DW_AT_decl_line:
      decl.SetLine(form_value.Unsigned());
      break;
    case DW_AT_decl_column:
      decl.SetColumn(form_value.Unsigned());
      break;

    case DW_AT_declaration:
      is_forward_declaration = form_value.Boolean();
      break;

    case DW_AT_encoding:
      encoding = form_value.Unsigned();
      break;

    case DW_AT_enum_class:
      is_scoped_enum = form_value.Boolean();
      break;

    case DW_AT_explicit:
      is_explicit = form_value.Boolean();
      break;

    case DW_AT_external:
      if (form_value.Unsigned())
        storage = clang::SC_Extern;
      break;

    case DW_AT_inline:
      is_inline = form_value.Boolean();
      break;

    case DW_AT_linkage_name:
    case DW_AT_MIPS_linkage_name:
      mangled_name = form_value.AsCString();
      break;

    case DW_AT_name:
      name.SetCString(form_value.AsCString());
      break;

    case DW_AT_object_pointer:
      object_pointer = form_value.Reference();
      break;

    case DW_AT_signature:
      signature = form_value;
      break;

    case DW_AT_specification:
      specification = form_value;
      break;

    case DW_AT_type:
      type = form_value;
      break;

    case DW_AT_virtuality:
      is_virtual = form_value.Boolean();
      break;

    case DW_AT_APPLE_objc_complete_type:
      is_complete_objc_class = form_value.Signed();
      break;

    case DW_AT_APPLE_runtime_class:
      class_language = (LanguageType)form_value.Signed();
      break;

    case DW_AT_GNU_vector:
      is_vector = form_value.Boolean();
      break;
    }
  }
}

static std::string GetUnitName(const DWARFDIE &die) {
  if (DWARFUnit *unit = die.GetCU())
    return unit->GetAbsolutePath().GetPath();
  return "<missing DWARF unit path>";
}

TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
                                               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;
    clang::DeclContext *context =
        GetClangDeclContextContainingDIE(die, &context_die);

    dwarf->GetObjectFile()->GetModule()->LogMessage(
        log,
        "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die "
        "0x%8.8x)) %s name = '%s')",
        die.GetOffset(), static_cast<void *>(context), context_die.GetOffset(),
        die.GetTagAsCString(), die.GetName());
  }


  Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());
  if (type_ptr == DIE_IS_BEING_PARSED)
    return nullptr;
  if (type_ptr)
    return type_ptr->shared_from_this();
  // Set a bit that lets us know that we are currently parsing this
  dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;

  ParsedDWARFTypeAttributes attrs(die);

  if (DWARFDIE signature_die = attrs.signature.Reference()) {
    if (TypeSP type_sp =
            ParseTypeFromDWARF(sc, signature_die, type_is_new_ptr)) {
      dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
      if (clang::DeclContext *decl_ctx =
              GetCachedClangDeclContextForDIE(signature_die))
        LinkDeclContextToDIE(decl_ctx, die);
      return type_sp;
    }
    return nullptr;
  }

  if (type_is_new_ptr)
    *type_is_new_ptr = true;

  const dw_tag_t tag = die.Tag();

  Type::ResolveState resolve_state = Type::eResolveStateUnresolved;

  Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
  CompilerType clang_type;

  TypeSP type_sp;
  LanguageType cu_language = die.GetLanguage();
  switch (tag) {
  case DW_TAG_typedef:
  case DW_TAG_base_type:
  case DW_TAG_pointer_type:
  case DW_TAG_reference_type:
  case DW_TAG_rvalue_reference_type:
  case DW_TAG_const_type:
  case DW_TAG_restrict_type:
  case DW_TAG_volatile_type:
  case DW_TAG_unspecified_type: {
    if (tag == DW_TAG_typedef && attrs.type.IsValid()) {
      // Try to parse a typedef from the DWO file first as modules can
      // contain typedef'ed structures that have no names like:
      //
      //  typedef struct { int a; } Foo;
      //
      // In this case we will have a structure with no name and a typedef
      // named "Foo" that points to this unnamed structure. The name in the
      // typedef is the only identifier for the struct, so always try to
      // get typedefs from DWO files if possible.
      //
      // The type_sp returned will be empty if the typedef doesn't exist in
      // a DWO file, so it is cheap to call this function just to check.
      //
      // If we don't do this we end up creating a TypeSP that says this is
      // a typedef to type 0x123 (the DW_AT_type value would be 0x123 in
      // the DW_TAG_typedef), and this is the unnamed structure type. We
      // will have a hard time tracking down an unnammed structure type in
      // the module DWO file, so we make sure we don't get into this
      // situation by always resolving typedefs from the DWO file.
      const DWARFDIE encoding_die = attrs.type.Reference();

      // First make sure that the die that this is typedef'ed to _is_ just
      // a declaration (DW_AT_declaration == 1), not a full definition
      // since template types can't be represented in modules since only
      // concrete instances of templates are ever emitted and modules won't
      // contain those
      if (encoding_die &&
          encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
        type_sp = ParseTypeFromDWO(die, log);
        if (type_sp)
          return type_sp;
      }
    }

    DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n",
                 die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr,
                 encoding_uid.Reference());

    switch (tag) {
    default:
      break;

    case DW_TAG_unspecified_type:
      if (attrs.name == "nullptr_t" || attrs.name == "decltype(nullptr)") {
        resolve_state = Type::eResolveStateFull;
        clang_type = m_ast.GetBasicType(eBasicTypeNullPtr);
        break;
      }
      // Fall through to base type below in case we can handle the type
      // there...
      LLVM_FALLTHROUGH;

    case DW_TAG_base_type:
      resolve_state = Type::eResolveStateFull;
      clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
          attrs.name.GetCString(), attrs.encoding,
          attrs.byte_size.getValueOr(0) * 8);
      break;

    case DW_TAG_pointer_type:
      encoding_data_type = Type::eEncodingIsPointerUID;
      break;
    case DW_TAG_reference_type:
      encoding_data_type = Type::eEncodingIsLValueReferenceUID;
      break;
    case DW_TAG_rvalue_reference_type:
      encoding_data_type = Type::eEncodingIsRValueReferenceUID;
      break;
    case DW_TAG_typedef:
      encoding_data_type = Type::eEncodingIsTypedefUID;
      break;
    case DW_TAG_const_type:
      encoding_data_type = Type::eEncodingIsConstUID;
      break;
    case DW_TAG_restrict_type:
      encoding_data_type = Type::eEncodingIsRestrictUID;
      break;
    case DW_TAG_volatile_type:
      encoding_data_type = Type::eEncodingIsVolatileUID;
      break;
    }

    if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID ||
                        encoding_data_type == Type::eEncodingIsTypedefUID)) {
      if (tag == DW_TAG_pointer_type) {
        DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type);

        if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) {
          // Blocks have a __FuncPtr inside them which is a pointer to a
          // function of the proper type.

          for (DWARFDIE child_die = target_die.GetFirstChild();
               child_die.IsValid(); child_die = child_die.GetSibling()) {
            if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""),
                        "__FuncPtr")) {
              DWARFDIE function_pointer_type =
                  child_die.GetReferencedDIE(DW_AT_type);

              if (function_pointer_type) {
                DWARFDIE function_type =
                    function_pointer_type.GetReferencedDIE(DW_AT_type);

                bool function_type_is_new_pointer;
                TypeSP lldb_function_type_sp = ParseTypeFromDWARF(
                    sc, function_type, &function_type_is_new_pointer);

                if (lldb_function_type_sp) {
                  clang_type = m_ast.CreateBlockPointerType(
                      lldb_function_type_sp->GetForwardCompilerType());
                  encoding_data_type = Type::eEncodingIsUID;
                  attrs.type.Clear();
                  resolve_state = Type::eResolveStateFull;
                }
              }

              break;
            }
          }
        }
      }

      if (cu_language == eLanguageTypeObjC ||
          cu_language == eLanguageTypeObjC_plus_plus) {
        if (attrs.name) {
          static ConstString g_objc_type_name_id("id");
          static ConstString g_objc_type_name_Class("Class");
          static ConstString g_objc_type_name_selector("SEL");

          if (attrs.name == g_objc_type_name_id) {
            if (log)
              dwarf->GetObjectFile()->GetModule()->LogMessage(
                  log,
                  "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
                  "is Objective-C 'id' built-in type.",
                  die.GetOffset(), die.GetTagAsCString(), die.GetName());
            clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
            encoding_data_type = Type::eEncodingIsUID;
            attrs.type.Clear();
            resolve_state = Type::eResolveStateFull;

          } else if (attrs.name == g_objc_type_name_Class) {
            if (log)
              dwarf->GetObjectFile()->GetModule()->LogMessage(
                  log,
                  "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
                  "is Objective-C 'Class' built-in type.",
                  die.GetOffset(), die.GetTagAsCString(), die.GetName());
            clang_type = m_ast.GetBasicType(eBasicTypeObjCClass);
            encoding_data_type = Type::eEncodingIsUID;
            attrs.type.Clear();
            resolve_state = Type::eResolveStateFull;
          } else if (attrs.name == g_objc_type_name_selector) {
            if (log)
              dwarf->GetObjectFile()->GetModule()->LogMessage(
                  log,
                  "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
                  "is Objective-C 'selector' built-in type.",
                  die.GetOffset(), die.GetTagAsCString(), die.GetName());
            clang_type = m_ast.GetBasicType(eBasicTypeObjCSel);
            encoding_data_type = Type::eEncodingIsUID;
            attrs.type.Clear();
            resolve_state = Type::eResolveStateFull;
          }
        } else if (encoding_data_type == Type::eEncodingIsPointerUID &&
                   attrs.type.IsValid()) {
          // Clang sometimes erroneously emits id as objc_object*.  In that
          // case we fix up the type to "id".

          const DWARFDIE encoding_die = attrs.type.Reference();

          if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) {
            if (const char *struct_name = encoding_die.GetName()) {
              if (!strcmp(struct_name, "objc_object")) {
                if (log)
                  dwarf->GetObjectFile()->GetModule()->LogMessage(
                      log,
                      "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s "
                      "'%s' is 'objc_object*', which we overrode to "
                      "'id'.",
                      die.GetOffset(), die.GetTagAsCString(), die.GetName());
                clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
                encoding_data_type = Type::eEncodingIsUID;
                attrs.type.Clear();
                resolve_state = Type::eResolveStateFull;
              }
            }
          }
        }
      }
    }

    type_sp = std::make_shared<Type>(
        die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
        dwarf->GetUID(attrs.type.Reference()), encoding_data_type, &attrs.decl,
        clang_type, resolve_state);

    dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
  } break;

  case DW_TAG_structure_type:
  case DW_TAG_union_type:
  case DW_TAG_class_type: {
    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) {
      type_sp = ParseTypeFromDWO(die, log);
      if (type_sp)
        return type_sp;

      DWARFDeclContext die_decl_ctx;
      die.GetDWARFDeclContext(die_decl_ctx);

      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;
      }
    }
    DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
                 DW_TAG_value_to_name(tag), type_name_cstr);

    CompilerType enumerator_clang_type;
    clang_type.SetCompilerType(
        &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
    if (!clang_type) {
      if (attrs.type.IsValid()) {
        Type *enumerator_type =
            dwarf->ResolveTypeUID(attrs.type.Reference(), true);
        if (enumerator_type)
          enumerator_clang_type = enumerator_type->GetFullCompilerType();
      }

      if (!enumerator_clang_type) {
        if (attrs.byte_size) {
          enumerator_clang_type =
              m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
                  NULL, DW_ATE_signed, *attrs.byte_size * 8);
        } else {
          enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt);
        }
      }

      clang_type = m_ast.CreateEnumerationType(
          attrs.name.GetCString(),
          GetClangDeclContextContainingDIE(die, nullptr), attrs.decl,
          enumerator_clang_type, attrs.is_scoped_enum);
    } else {
      enumerator_clang_type =
          m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType());
    }

    LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type),
                         die);

    type_sp = std::make_shared<Type>(
        die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
        dwarf->GetUID(attrs.type.Reference()), Type::eEncodingIsUID,
        &attrs.decl, clang_type, Type::eResolveStateForward);

    if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
      if (die.HasChildren()) {
        bool is_signed = false;
        enumerator_clang_type.IsIntegerType(is_signed);
        ParseChildEnumerators(clang_type, is_signed,
                              type_sp->GetByteSize().getValueOr(0), die);
      }
      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());
    }
  } break;

  case DW_TAG_inlined_subroutine:
  case DW_TAG_subprogram:
  case DW_TAG_subroutine_type: {
    bool is_variadic = false;
    bool is_static = false;
    bool has_template_params = false;

    unsigned type_quals = 0;

    std::string object_pointer_name;
    if (attrs.object_pointer) {
      const char *object_pointer_name_cstr = attrs.object_pointer.GetName();
      if (object_pointer_name_cstr)
        object_pointer_name = object_pointer_name_cstr;
    }

    DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
                 DW_TAG_value_to_name(tag), type_name_cstr);

    CompilerType return_clang_type;
    Type *func_type = NULL;

    if (attrs.type.IsValid())
      func_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);

    if (func_type)
      return_clang_type = func_type->GetForwardCompilerType();
    else
      return_clang_type = m_ast.GetBasicType(eBasicTypeVoid);

    std::vector<CompilerType> function_param_types;
    std::vector<clang::ParmVarDecl *> function_param_decls;

    // Parse the function children for the parameters

    DWARFDIE decl_ctx_die;
    clang::DeclContext *containing_decl_ctx =
        GetClangDeclContextContainingDIE(die, &decl_ctx_die);
    const clang::Decl::Kind containing_decl_kind =
        containing_decl_ctx->getDeclKind();

    bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind);
    // Start off static. This will be set to false in
    // ParseChildParameters(...) if we find a "this" parameters as the
    // first parameter
    if (is_cxx_method) {
      is_static = true;
    }

    if (die.HasChildren()) {
      bool skip_artificial = true;
      ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static,
                           is_variadic, has_template_params,
                           function_param_types, function_param_decls,
                           type_quals);
    }

    bool ignore_containing_context = false;
    // Check for templatized class member functions. If we had any
    // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter
    // the DW_TAG_subprogram DIE, then we can't let this become a method in
    // a class. Why? Because templatized functions are only emitted if one
    // of the templatized methods is used in the current compile unit and
    // we will end up with classes that may or may not include these member
    // functions and this means one class won't match another class
    // definition and it affects our ability to use a class in the clang
    // expression parser. So for the greater good, we currently must not
    // allow any template member functions in a class definition.
    if (is_cxx_method && has_template_params) {
      ignore_containing_context = true;
      is_cxx_method = false;
    }

    // clang_type will get the function prototype clang type after this
    // call
    clang_type = m_ast.CreateFunctionType(
        return_clang_type, function_param_types.data(),
        function_param_types.size(), is_variadic, type_quals);

    if (attrs.name) {
      bool type_handled = false;
      if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {
        ObjCLanguage::MethodName objc_method(attrs.name.GetStringRef(), true);
        if (objc_method.IsValid(true)) {
          CompilerType class_opaque_type;
          ConstString class_name(objc_method.GetClassName());
          if (class_name) {
            TypeSP complete_objc_class_type_sp(
                dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(),
                                                            class_name, false));

            if (complete_objc_class_type_sp) {
              CompilerType type_clang_forward_type =
                  complete_objc_class_type_sp->GetForwardCompilerType();
              if (ClangASTContext::IsObjCObjectOrInterfaceType(
                      type_clang_forward_type))
                class_opaque_type = type_clang_forward_type;
            }
          }

          if (class_opaque_type) {
            // If accessibility isn't set to anything valid, assume public
            // for now...
            if (attrs.accessibility == eAccessNone)
              attrs.accessibility = eAccessPublic;

            clang::ObjCMethodDecl *objc_method_decl =
                m_ast.AddMethodToObjCObjectType(
                    class_opaque_type, attrs.name.GetCString(), clang_type,
                    attrs.accessibility, attrs.is_artificial, is_variadic);
            type_handled = objc_method_decl != NULL;
            if (type_handled) {
              LinkDeclContextToDIE(
                  ClangASTContext::GetAsDeclContext(objc_method_decl), die);
              m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID());
            } else {
              dwarf->GetObjectFile()->GetModule()->ReportError(
                  "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), "
                  "please file a bug and attach the file at the start of "
                  "this error message",
                  die.GetOffset(), tag, DW_TAG_value_to_name(tag));
            }
          }
        } else if (is_cxx_method) {
          // Look at the parent of this DIE and see if is is a class or
          // struct and see if this is actually a C++ method
          Type *class_type = dwarf->ResolveType(decl_ctx_die);
          if (class_type) {
            bool alternate_defn = false;
            if (class_type->GetID() != decl_ctx_die.GetID() ||
                decl_ctx_die.GetContainingDWOModuleDIE()) {
              alternate_defn = true;

              // 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_ptr = dwarf->GetDIEToType()[die.GetDIE()];
                if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
                  type_sp = type_ptr->shared_from_this();
                  break;
                }
              }
            }

            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
              // completed so that the m_die_to_decl_ctx for the method in
              // the specification has a valid clang decl context.
              class_type->GetForwardCompilerType();
              // If we have a specification, then the function type should
              // have been made with the specification and not with this
              // die.
              DWARFDIE spec_die = attrs.specification.Reference();
              clang::DeclContext *spec_clang_decl_ctx =
                  GetClangDeclContextForDIE(spec_die);
              if (spec_clang_decl_ctx) {
                LinkDeclContextToDIE(spec_clang_decl_ctx, die);
              } else {
                dwarf->GetObjectFile()->GetModule()->ReportWarning(
                    "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x"
                    ") has no decl\n",
                    die.GetID(), spec_die.GetOffset());
              }
              type_handled = true;
            } else if (attrs.abstract_origin.IsValid()) {
              // We have a specification which we are going to base our
              // function prototype off of, so we need this type to be
              // completed so that the m_die_to_decl_ctx for the method in
              // the abstract origin has a valid clang decl context.
              class_type->GetForwardCompilerType();

              DWARFDIE abs_die = attrs.abstract_origin.Reference();
              clang::DeclContext *abs_clang_decl_ctx =
                  GetClangDeclContextForDIE(abs_die);
              if (abs_clang_decl_ctx) {
                LinkDeclContextToDIE(abs_clang_decl_ctx, die);
              } else {
                dwarf->GetObjectFile()->GetModule()->ReportWarning(
                    "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x"
                    ") has no decl\n",
                    die.GetID(), abs_die.GetOffset());
              }
              type_handled = true;
            } else {
              CompilerType class_opaque_type =
                  class_type->GetForwardCompilerType();
              if (ClangASTContext::IsCXXClassType(class_opaque_type)) {
                if (class_opaque_type.IsBeingDefined() || alternate_defn) {
                  if (!is_static && !die.HasChildren()) {
                    // We have a C++ member function with no children (this
                    // pointer!) and clang will get mad if we try and make
                    // a function that isn't well formed in the DWARF, so
                    // we will just skip it...
                    type_handled = true;
                  } else {
                    bool add_method = true;
                    if (alternate_defn) {
                      // If an alternate definition for the class exists,
                      // then add the method only if an equivalent is not
                      // already present.
                      clang::CXXRecordDecl *record_decl =
                          m_ast.GetAsCXXRecordDecl(
                              class_opaque_type.GetOpaqueQualType());
                      if (record_decl) {
                        for (auto method_iter = record_decl->method_begin();
                             method_iter != record_decl->method_end();
                             method_iter++) {
                          clang::CXXMethodDecl *method_decl = *method_iter;
                          if (method_decl->getNameInfo().getAsString() ==
                              attrs.name.GetStringRef()) {
                            if (method_decl->getType() ==
                                ClangUtil::GetQualType(clang_type)) {
                              add_method = false;
                              LinkDeclContextToDIE(
                                  ClangASTContext::GetAsDeclContext(
                                      method_decl),
                                  die);
                              type_handled = true;

                              break;
                            }
                          }
                        }
                      }
                    }

                    if (add_method) {
                      llvm::PrettyStackTraceFormat stack_trace(
                          "SymbolFileDWARF::ParseType() is adding a method "
                          "%s to class %s in DIE 0x%8.8" PRIx64 " from %s",
                          attrs.name.GetCString(),
                          class_type->GetName().GetCString(), die.GetID(),
                          dwarf->GetObjectFile()
                              ->GetFileSpec()
                              .GetPath()
                              .c_str());

                      const bool is_attr_used = false;
                      // Neither GCC 4.2 nor clang++ currently set a valid
                      // accessibility in the DWARF for C++ methods...
                      // Default to public for now...
                      if (attrs.accessibility == eAccessNone)
                        attrs.accessibility = eAccessPublic;

                      clang::CXXMethodDecl *cxx_method_decl =
                          m_ast.AddMethodToCXXRecordType(
                              class_opaque_type.GetOpaqueQualType(),
                              attrs.name.GetCString(), attrs.mangled_name,
                              clang_type, attrs.accessibility, attrs.is_virtual,
                              is_static, attrs.is_inline, attrs.is_explicit,
                              is_attr_used, attrs.is_artificial);

                      type_handled = cxx_method_decl != NULL;
                      // Artificial methods are always handled even when we
                      // don't create a new declaration for them.
                      type_handled |= attrs.is_artificial;

                      if (cxx_method_decl) {
                        LinkDeclContextToDIE(
                            ClangASTContext::GetAsDeclContext(cxx_method_decl),
                            die);

                        ClangASTMetadata metadata;
                        metadata.SetUserID(die.GetID());

                        if (!object_pointer_name.empty()) {
                          metadata.SetObjectPtrName(
                              object_pointer_name.c_str());
                          LLDB_LOGF(log,
                                    "Setting object pointer name: %s on method "
                                    "object %p.\n",
                                    object_pointer_name.c_str(),
                                    static_cast<void *>(cxx_method_decl));
                        }
                        m_ast.SetMetadata(cxx_method_decl, metadata);
                      } else {
                        ignore_containing_context = true;
                      }
                    }
                  }
                } else {
                  // We were asked to parse the type for a method in a
                  // class, yet the class hasn't been asked to complete
                  // itself through the clang::ExternalASTSource protocol,
                  // so we need to just have the class complete itself and
                  // do things the right way, then our
                  // DIE should then have an entry in the
                  // dwarf->GetDIEToType() map. First
                  // we need to modify the dwarf->GetDIEToType() so it
                  // doesn't think we are trying to parse this DIE
                  // anymore...
                  dwarf->GetDIEToType()[die.GetDIE()] = NULL;

                  // Now we get the full type to force our class type to
                  // complete itself using the clang::ExternalASTSource
                  // protocol which will parse all base classes and all
                  // methods (including the method for this DIE).
                  class_type->GetFullCompilerType();

                  // The type for this DIE should have been filled in the
                  // function call above
                  type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
                  if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
                    type_sp = type_ptr->shared_from_this();
                    break;
                  }

                  // FIXME This is fixing some even uglier behavior but we
                  // really need to
                  // uniq the methods of each class as well as the class
                  // itself. <rdar://problem/11240464>
                  type_handled = true;
                }
              }
            }
          }
        }
      }

      if (!type_handled) {
        clang::FunctionDecl *function_decl = nullptr;
        clang::FunctionDecl *template_function_decl = nullptr;

        if (attrs.abstract_origin.IsValid()) {
          DWARFDIE abs_die = attrs.abstract_origin.Reference();

          if (dwarf->ResolveType(abs_die)) {
            function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>(
                GetCachedClangDeclContextForDIE(abs_die));

            if (function_decl) {
              LinkDeclContextToDIE(function_decl, die);
            }
          }
        }

        if (!function_decl) {
          // We just have a function that isn't part of a class
          function_decl = m_ast.CreateFunctionDeclaration(
              ignore_containing_context ? m_ast.GetTranslationUnitDecl()
                                        : containing_decl_ctx,
              attrs.name.GetCString(), clang_type, attrs.storage,
              attrs.is_inline);

          if (has_template_params) {
            ClangASTContext::TemplateParameterInfos template_param_infos;
            ParseTemplateParameterInfos(die, template_param_infos);
            template_function_decl = m_ast.CreateFunctionDeclaration(
                ignore_containing_context ? m_ast.GetTranslationUnitDecl()
                                          : containing_decl_ctx,
                attrs.name.GetCString(), clang_type, attrs.storage,
                attrs.is_inline);
            clang::FunctionTemplateDecl *func_template_decl =
                m_ast.CreateFunctionTemplateDecl(
                    containing_decl_ctx, template_function_decl,
                    attrs.name.GetCString(), template_param_infos);
            m_ast.CreateFunctionTemplateSpecializationInfo(
                function_decl, func_template_decl, template_param_infos);
          }

          lldbassert(function_decl);

          if (function_decl) {
            LinkDeclContextToDIE(function_decl, die);

            if (!function_param_decls.empty()) {
              m_ast.SetFunctionParameters(function_decl,
                                          &function_param_decls.front(),
                                          function_param_decls.size());
              if (template_function_decl)
                m_ast.SetFunctionParameters(template_function_decl,
                                            &function_param_decls.front(),
                                            function_param_decls.size());
            }

            ClangASTMetadata metadata;
            metadata.SetUserID(die.GetID());

            if (!object_pointer_name.empty()) {
              metadata.SetObjectPtrName(object_pointer_name.c_str());
              LLDB_LOGF(log,
                        "Setting object pointer name: %s on function "
                        "object %p.",
                        object_pointer_name.c_str(),
                        static_cast<void *>(function_decl));
            }
            m_ast.SetMetadata(function_decl, metadata);
          }
        }
      }
    }
    type_sp = std::make_shared<Type>(
        die.GetID(), dwarf, attrs.name, llvm::None, nullptr, LLDB_INVALID_UID,
        Type::eEncodingIsUID, &attrs.decl, clang_type, Type::eResolveStateFull);
    assert(type_sp.get());
  } break;

  case DW_TAG_array_type: {
    DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
                 DW_TAG_value_to_name(tag), type_name_cstr);

    DWARFDIE type_die = attrs.type.Reference();
    Type *element_type = dwarf->ResolveTypeUID(type_die, true);

    if (element_type) {
      auto array_info = ParseChildArrayInfo(die);
      if (array_info) {
        attrs.byte_stride = array_info->byte_stride;
        attrs.bit_stride = array_info->bit_stride;
      }
      if (attrs.byte_stride == 0 && attrs.bit_stride == 0)
        attrs.byte_stride = element_type->GetByteSize().getValueOr(0);
      CompilerType array_element_type = element_type->GetForwardCompilerType();

      if (ClangASTContext::IsCXXClassType(array_element_type) &&
          !array_element_type.GetCompleteType()) {
        ModuleSP module_sp = die.GetModule();
        if (module_sp) {
          if (die.GetCU()->GetProducer() == eProducerClang)
            module_sp->ReportError(
                "DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
                "class/union/struct element type DIE 0x%8.8x that is a "
                "forward declaration, not a complete definition.\nTry "
                "compiling the source file with -fstandalone-debug or "
                "disable -gmodules",
                die.GetOffset(), type_die.GetOffset());
          else
            module_sp->ReportError(
                "DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
                "class/union/struct element type DIE 0x%8.8x that is a "
                "forward declaration, not a complete definition.\nPlease "
                "file a bug against the compiler and include the "
                "preprocessed output for %s",
                die.GetOffset(), type_die.GetOffset(),
                GetUnitName(die).c_str());
        }

        // We have no choice other than to pretend that the element class
        // type is complete. If we don't do this, clang will crash when
        // trying to layout the class. Since we provide layout
        // assistance, all ivars in this class and other classes will be
        // fine, this is the best we can do short of crashing.
        if (ClangASTContext::StartTagDeclarationDefinition(
                array_element_type)) {
          ClangASTContext::CompleteTagDeclarationDefinition(array_element_type);
        } else {
          module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to "
                                 "start its definition.\nPlease file a "
                                 "bug and attach the file at the start "
                                 "of this error message",
                                 type_die.GetOffset());
        }
      }

      uint64_t array_element_bit_stride =
          attrs.byte_stride * 8 + attrs.bit_stride;
      if (array_info && array_info->element_orders.size() > 0) {
        uint64_t num_elements = 0;
        auto end = array_info->element_orders.rend();
        for (auto pos = array_info->element_orders.rbegin(); pos != end;
             ++pos) {
          num_elements = *pos;
          clang_type = m_ast.CreateArrayType(array_element_type, num_elements,
                                             attrs.is_vector);
          array_element_type = clang_type;
          array_element_bit_stride =
              num_elements ? array_element_bit_stride * num_elements
                           : array_element_bit_stride;
        }
      } else {
        clang_type = m_ast.CreateArrayType(array_element_type, 0, attrs.is_vector);
      }
      ConstString empty_name;
      type_sp = std::make_shared<Type>(
          die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, nullptr,
          dwarf->GetUID(type_die), Type::eEncodingIsUID, &attrs.decl,
          clang_type, Type::eResolveStateFull);
      type_sp->SetEncodingType(element_type);
      m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(), die.GetID());
    }
  } break;

  case DW_TAG_ptr_to_member_type: {
    Type *pointee_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);
    Type *class_type =
        dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true);

    CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType();
    CompilerType class_clang_type = class_type->GetLayoutCompilerType();

    clang_type = ClangASTContext::CreateMemberPointerType(class_clang_type,
                                                          pointee_clang_type);

    if (llvm::Optional<uint64_t> clang_type_size =
            clang_type.GetByteSize(nullptr)) {
      type_sp = std::make_shared<Type>(
          die.GetID(), dwarf, attrs.name, *clang_type_size, nullptr,
          LLDB_INVALID_UID, Type::eEncodingIsUID, nullptr, clang_type,
          Type::eResolveStateForward);
    }

    break;
  }
  default:
    dwarf->GetObjectFile()->GetModule()->ReportError(
        "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and "
        "attach the file at the start of this error message",
        die.GetOffset(), tag, DW_TAG_value_to_name(tag));
    break;
  }

  // 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;

  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;
}

// DWARF parsing functions

class DWARFASTParserClang::DelayedAddObjCClassProperty {
public:
  DelayedAddObjCClassProperty(
      const CompilerType &class_opaque_type, const char *property_name,
      const CompilerType &property_opaque_type, // The property type is only
                                                // required if you don't have an
                                                // ivar decl
      clang::ObjCIvarDecl *ivar_decl, const char *property_setter_name,
      const char *property_getter_name, uint32_t property_attributes,
      const ClangASTMetadata *metadata)
      : m_class_opaque_type(class_opaque_type), m_property_name(property_name),
        m_property_opaque_type(property_opaque_type), m_ivar_decl(ivar_decl),
        m_property_setter_name(property_setter_name),
        m_property_getter_name(property_getter_name),
        m_property_attributes(property_attributes) {
    if (metadata != nullptr) {
      m_metadata_up.reset(new ClangASTMetadata());
      *m_metadata_up = *metadata;
    }
  }

  DelayedAddObjCClassProperty(const DelayedAddObjCClassProperty &rhs) {
    *this = rhs;
  }

  DelayedAddObjCClassProperty &
  operator=(const DelayedAddObjCClassProperty &rhs) {
    m_class_opaque_type = rhs.m_class_opaque_type;
    m_property_name = rhs.m_property_name;
    m_property_opaque_type = rhs.m_property_opaque_type;
    m_ivar_decl = rhs.m_ivar_decl;
    m_property_setter_name = rhs.m_property_setter_name;
    m_property_getter_name = rhs.m_property_getter_name;
    m_property_attributes = rhs.m_property_attributes;

    if (rhs.m_metadata_up) {
      m_metadata_up.reset(new ClangASTMetadata());
      *m_metadata_up = *rhs.m_metadata_up;
    }
    return *this;
  }

  bool Finalize() {
    return ClangASTContext::AddObjCClassProperty(
        m_class_opaque_type, m_property_name, m_property_opaque_type,
        m_ivar_decl, m_property_setter_name, m_property_getter_name,
        m_property_attributes, m_metadata_up.get());
  }

private:
  CompilerType m_class_opaque_type;
  const char *m_property_name;
  CompilerType m_property_opaque_type;
  clang::ObjCIvarDecl *m_ivar_decl;
  const char *m_property_setter_name;
  const char *m_property_getter_name;
  uint32_t m_property_attributes;
  std::unique_ptr<ClangASTMetadata> m_metadata_up;
};

bool DWARFASTParserClang::ParseTemplateDIE(
    const DWARFDIE &die,
    ClangASTContext::TemplateParameterInfos &template_param_infos) {
  const dw_tag_t tag = die.Tag();
  bool is_template_template_argument = false;

  switch (tag) {
  case DW_TAG_GNU_template_parameter_pack: {
    template_param_infos.packed_args.reset(
      new ClangASTContext::TemplateParameterInfos);
    for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid();
         child_die = child_die.GetSibling()) {
      if (!ParseTemplateDIE(child_die, *template_param_infos.packed_args))
        return false;
    }
    if (const char *name = die.GetName()) {
      template_param_infos.pack_name = name;
    }
    return true;
  }
  case DW_TAG_GNU_template_template_param:
    is_template_template_argument = true;
    LLVM_FALLTHROUGH;
  case DW_TAG_template_type_parameter:
  case DW_TAG_template_value_parameter: {
    DWARFAttributes attributes;
    const size_t num_attributes = die.GetAttributes(attributes);
    const char *name = nullptr;
    const char *template_name = nullptr;
    CompilerType clang_type;
    uint64_t uval64 = 0;
    bool uval64_valid = false;
    if (num_attributes > 0) {
      DWARFFormValue form_value;
      for (size_t i = 0; i < num_attributes; ++i) {
        const dw_attr_t attr = attributes.AttributeAtIndex(i);

        switch (attr) {
        case DW_AT_name:
          if (attributes.ExtractFormValueAtIndex(i, form_value))
            name = form_value.AsCString();
          break;

        case DW_AT_GNU_template_name:
          if (attributes.ExtractFormValueAtIndex(i, form_value))
            template_name = form_value.AsCString();
          break;

        case DW_AT_type:
          if (attributes.ExtractFormValueAtIndex(i, form_value)) {
            Type *lldb_type = die.ResolveTypeUID(form_value.Reference());
            if (lldb_type)
              clang_type = lldb_type->GetForwardCompilerType();
          }
          break;

        case DW_AT_const_value:
          if (attributes.ExtractFormValueAtIndex(i, form_value)) {
            uval64_valid = true;
            uval64 = form_value.Unsigned();
          }
          break;
        default:
          break;
        }
      }

      clang::ASTContext *ast = m_ast.getASTContext();
      if (!clang_type)
        clang_type = m_ast.GetBasicType(eBasicTypeVoid);

      if (!is_template_template_argument) {
        bool is_signed = false;
        if (name && name[0])
          template_param_infos.names.push_back(name);
        else
          template_param_infos.names.push_back(NULL);

        // Get the signed value for any integer or enumeration if available
        clang_type.IsIntegerOrEnumerationType(is_signed);

        if (tag == DW_TAG_template_value_parameter && uval64_valid) {
          llvm::Optional<uint64_t> size = clang_type.GetBitSize(nullptr);
          if (!size)
            return false;
          llvm::APInt apint(*size, uval64, is_signed);
          template_param_infos.args.push_back(
              clang::TemplateArgument(*ast, llvm::APSInt(apint, !is_signed),
                                      ClangUtil::GetQualType(clang_type)));
        } else {
          template_param_infos.args.push_back(
              clang::TemplateArgument(ClangUtil::GetQualType(clang_type)));
        }
      } else {
        auto *tplt_type = m_ast.CreateTemplateTemplateParmDecl(template_name);
        template_param_infos.names.push_back(name);
        template_param_infos.args.push_back(
            clang::TemplateArgument(clang::TemplateName(tplt_type)));
      }
    }
  }
    return true;

  default:
    break;
  }
  return false;
}

bool DWARFASTParserClang::ParseTemplateParameterInfos(
    const DWARFDIE &parent_die,
    ClangASTContext::TemplateParameterInfos &template_param_infos) {

  if (!parent_die)
    return false;

  for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
       die = die.GetSibling()) {
    const dw_tag_t tag = die.Tag();

    switch (tag) {
    case DW_TAG_template_type_parameter:
    case DW_TAG_template_value_parameter:
    case DW_TAG_GNU_template_parameter_pack:
    case DW_TAG_GNU_template_template_param:
      ParseTemplateDIE(die, template_param_infos);
      break;

    default:
      break;
    }
  }
  if (template_param_infos.args.empty())
    return false;
  return template_param_infos.args.size() == template_param_infos.names.size();
}

bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
                                                lldb_private::Type *type,
                                                CompilerType &clang_type) {
  SymbolFileDWARF *dwarf = die.GetDWARF();

  std::lock_guard<std::recursive_mutex> guard(
      dwarf->GetObjectFile()->GetModule()->GetMutex());

  // Disable external storage for this type so we don't get anymore
  // clang::ExternalASTSource queries for this type.
  m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), false);

  if (!die)
    return false;

#if defined LLDB_CONFIGURATION_DEBUG
  // For debugging purposes, the LLDB_DWARF_DONT_COMPLETE_TYPENAMES environment
  // variable can be set with one or more typenames separated by ';'
  // characters. This will cause this function to not complete any types whose
  // names match.
  //
  // Examples of setting this environment variable:
  //
  // LLDB_DWARF_DONT_COMPLETE_TYPENAMES=Foo
  // LLDB_DWARF_DONT_COMPLETE_TYPENAMES=Foo;Bar;Baz
  const char *dont_complete_typenames_cstr =
      getenv("LLDB_DWARF_DONT_COMPLETE_TYPENAMES");
  if (dont_complete_typenames_cstr && dont_complete_typenames_cstr[0]) {
    const char *die_name = die.GetName();
    if (die_name && die_name[0]) {
      const char *match = strstr(dont_complete_typenames_cstr, die_name);
      if (match) {
        size_t die_name_length = strlen(die_name);
        while (match) {
          const char separator_char = ';';
          const char next_char = match[die_name_length];
          if (next_char == '\0' || next_char == separator_char) {
            if (match == dont_complete_typenames_cstr ||
                match[-1] == separator_char)
              return false;
          }
          match = strstr(match + 1, die_name);
        }
      }
    }
  }
#endif

  const dw_tag_t tag = die.Tag();

  Log *log =
      nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
  if (log)
    dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
        log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...",
        die.GetID(), die.GetTagAsCString(), type->GetName().AsCString());
  assert(clang_type);
  DWARFAttributes attributes;
  switch (tag) {
  case DW_TAG_structure_type:
  case DW_TAG_union_type:
  case DW_TAG_class_type: {
    ClangASTImporter::LayoutInfo layout_info;

    {
      if (die.HasChildren()) {
        LanguageType class_language = eLanguageTypeUnknown;
        if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type)) {
          class_language = eLanguageTypeObjC;
          // For objective C we don't start the definition when the class is
          // created.
          ClangASTContext::StartTagDeclarationDefinition(clang_type);
        }

        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;
        }

        std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
        std::vector<int> member_accessibilities;
        bool is_a_class = false;
        // Parse members and base classes first
        std::vector<DWARFDIE> member_function_dies;

        DelayedPropertyList delayed_properties;
        ParseChildMembers(die, clang_type, class_language, bases,
                          member_accessibilities, member_function_dies,
                          delayed_properties, default_accessibility, is_a_class,
                          layout_info);

        // Now parse any methods if there were any...
        for (const DWARFDIE &die : member_function_dies)
          dwarf->ResolveType(die);

        if (class_language == eLanguageTypeObjC) {
          ConstString class_name(clang_type.GetTypeName());
          if (class_name) {
            DIEArray method_die_offsets;
            dwarf->GetObjCMethodDIEOffsets(class_name, method_die_offsets);

            if (!method_die_offsets.empty()) {
              DWARFDebugInfo *debug_info = dwarf->DebugInfo();

              const size_t num_matches = method_die_offsets.size();
              for (size_t i = 0; i < num_matches; ++i) {
                const DIERef &die_ref = method_die_offsets[i];
                DWARFDIE method_die = debug_info->GetDIE(die_ref);

                if (method_die)
                  method_die.ResolveType();
              }
            }

            for (DelayedPropertyList::iterator pi = delayed_properties.begin(),
                                               pe = delayed_properties.end();
                 pi != pe; ++pi)
              pi->Finalize();
          }
        }

        // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
        // need to tell the clang type it is actually a class.
        if (class_language != eLanguageTypeObjC) {
          if (is_a_class && tag_decl_kind != clang::TTK_Class)
            m_ast.SetTagTypeKind(ClangUtil::GetQualType(clang_type),
                                 clang::TTK_Class);
        }

        // Since DW_TAG_structure_type gets used for both classes and
        // structures, we may need to set any DW_TAG_member fields to have a
        // "private" access if none was specified. When we parsed the child
        // members we tracked that actual accessibility value for each
        // DW_TAG_member in the "member_accessibilities" array. If the value
        // for the member is zero, then it was set to the
        // "default_accessibility" which for structs was "public". Below we
        // correct this by setting any fields to "private" that weren't
        // correctly set.
        if (is_a_class && !member_accessibilities.empty()) {
          // This is a class and all members that didn't have their access
          // specified are private.
          m_ast.SetDefaultAccessForRecordFields(
              m_ast.GetAsRecordDecl(clang_type), eAccessPrivate,
              &member_accessibilities.front(), member_accessibilities.size());
        }

        if (!bases.empty()) {
          // Make sure all base classes refer to complete types and not forward
          // declarations. If we don't do this, clang will crash with an
          // assertion in the call to clang_type.TransferBaseClasses()
          for (const auto &base_class : bases) {
            clang::TypeSourceInfo *type_source_info =
                base_class->getTypeSourceInfo();
            if (type_source_info) {
              CompilerType base_class_type(
                  &m_ast, type_source_info->getType().getAsOpaquePtr());
              if (!base_class_type.GetCompleteType()) {
                auto module = dwarf->GetObjectFile()->GetModule();
                module->ReportError(":: Class '%s' has a base class '%s' which "
                                    "does not have a complete definition.",
                                    die.GetName(),
                                    base_class_type.GetTypeName().GetCString());
                if (die.GetCU()->GetProducer() == eProducerClang)
                  module->ReportError(":: Try compiling the source file with "
                                      "-fstandalone-debug.");

                // We have no choice other than to pretend that the base class
                // is complete. If we don't do this, clang will crash when we
                // call setBases() inside of
                // "clang_type.TransferBaseClasses()" below. Since we
                // provide layout assistance, all ivars in this class and other
                // classes will be fine, this is the best we can do short of
                // crashing.
                if (ClangASTContext::StartTagDeclarationDefinition(
                        base_class_type)) {
                  ClangASTContext::CompleteTagDeclarationDefinition(
                      base_class_type);
                }
              }
            }
          }

          m_ast.TransferBaseClasses(clang_type.GetOpaqueQualType(),
                                    std::move(bases));
        }
      }
    }

    m_ast.AddMethodOverridesForCXXRecordType(clang_type.GetOpaqueQualType());
    ClangASTContext::BuildIndirectFields(clang_type);
    ClangASTContext::CompleteTagDeclarationDefinition(clang_type);

    if (!layout_info.field_offsets.empty() ||
        !layout_info.base_offsets.empty() ||
        !layout_info.vbase_offsets.empty()) {
      if (type)
        layout_info.bit_size = type->GetByteSize().getValueOr(0) * 8;
      if (layout_info.bit_size == 0)
        layout_info.bit_size =
            die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;

      clang::CXXRecordDecl *record_decl =
          m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
      if (record_decl) {
        if (log) {
          ModuleSP module_sp = dwarf->GetObjectFile()->GetModule();

          if (module_sp) {
            module_sp->LogMessage(
                log,
                "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) "
                "caching layout info for record_decl = %p, bit_size = %" PRIu64
                ", alignment = %" PRIu64
                ", field_offsets[%u], base_offsets[%u], vbase_offsets[%u])",
                static_cast<void *>(clang_type.GetOpaqueQualType()),
                static_cast<void *>(record_decl), layout_info.bit_size,
                layout_info.alignment,
                static_cast<uint32_t>(layout_info.field_offsets.size()),
                static_cast<uint32_t>(layout_info.base_offsets.size()),
                static_cast<uint32_t>(layout_info.vbase_offsets.size()));

            uint32_t idx;
            {
              llvm::DenseMap<const clang::FieldDecl *, uint64_t>::const_iterator
                  pos,
                  end = layout_info.field_offsets.end();
              for (idx = 0, pos = layout_info.field_offsets.begin(); pos != end;
                   ++pos, ++idx) {
                module_sp->LogMessage(
                    log, "ClangASTContext::CompleteTypeFromDWARF (clang_type = "
                         "%p) field[%u] = { bit_offset=%u, name='%s' }",
                    static_cast<void *>(clang_type.GetOpaqueQualType()), idx,
                    static_cast<uint32_t>(pos->second),
                    pos->first->getNameAsString().c_str());
              }
            }

            {
              llvm::DenseMap<const clang::CXXRecordDecl *,
                             clang::CharUnits>::const_iterator base_pos,
                  base_end = layout_info.base_offsets.end();
              for (idx = 0, base_pos = layout_info.base_offsets.begin();
                   base_pos != base_end; ++base_pos, ++idx) {
                module_sp->LogMessage(
                    log, "ClangASTContext::CompleteTypeFromDWARF (clang_type = "
                         "%p) base[%u] = { byte_offset=%u, name='%s' }",
                    clang_type.GetOpaqueQualType(), idx,
                    (uint32_t)base_pos->second.getQuantity(),
                    base_pos->first->getNameAsString().c_str());
              }
            }
            {
              llvm::DenseMap<const clang::CXXRecordDecl *,
                             clang::CharUnits>::const_iterator vbase_pos,
                  vbase_end = layout_info.vbase_offsets.end();
              for (idx = 0, vbase_pos = layout_info.vbase_offsets.begin();
                   vbase_pos != vbase_end; ++vbase_pos, ++idx) {
                module_sp->LogMessage(
                    log, "ClangASTContext::CompleteTypeFromDWARF (clang_type = "
                         "%p) vbase[%u] = { byte_offset=%u, name='%s' }",
                    static_cast<void *>(clang_type.GetOpaqueQualType()), idx,
                    static_cast<uint32_t>(vbase_pos->second.getQuantity()),
                    vbase_pos->first->getNameAsString().c_str());
              }
            }
          }
        }
        GetClangASTImporter().InsertRecordDecl(record_decl, layout_info);
      }
    }
  }

    return (bool)clang_type;

  case DW_TAG_enumeration_type:
    if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
      if (die.HasChildren()) {
        bool is_signed = false;
        clang_type.IsIntegerType(is_signed);
        ParseChildEnumerators(clang_type, is_signed,
                              type->GetByteSize().getValueOr(0), die);
      }
      ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
    }
    return (bool)clang_type;

  default:
    assert(false && "not a forward clang type decl!");
    break;
  }

  return false;
}

void DWARFASTParserClang::EnsureAllDIEsInDeclContextHaveBeenParsed(
    lldb_private::CompilerDeclContext decl_context) {
  auto opaque_decl_ctx =
      (clang::DeclContext *)decl_context.GetOpaqueDeclContext();
  for (auto it = m_decl_ctx_to_die.find(opaque_decl_ctx);
       it != m_decl_ctx_to_die.end() && it->first == opaque_decl_ctx;
       it = m_decl_ctx_to_die.erase(it))
    for (DWARFDIE decl = it->second.GetFirstChild(); decl;
         decl = decl.GetSibling())
      GetClangDeclForDIE(decl);
}

CompilerDecl DWARFASTParserClang::GetDeclForUIDFromDWARF(const DWARFDIE &die) {
  clang::Decl *clang_decl = GetClangDeclForDIE(die);
  if (clang_decl != nullptr)
    return CompilerDecl(&m_ast, clang_decl);
  return CompilerDecl();
}

CompilerDeclContext
DWARFASTParserClang::GetDeclContextForUIDFromDWARF(const DWARFDIE &die) {
  clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE(die);
  if (clang_decl_ctx)
    return CompilerDeclContext(&m_ast, clang_decl_ctx);
  return CompilerDeclContext();
}

CompilerDeclContext
DWARFASTParserClang::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) {
  clang::DeclContext *clang_decl_ctx =
      GetClangDeclContextContainingDIE(die, nullptr);
  if (clang_decl_ctx)
    return CompilerDeclContext(&m_ast, clang_decl_ctx);
  return CompilerDeclContext();
}

size_t DWARFASTParserClang::ParseChildEnumerators(
    lldb_private::CompilerType &clang_type, bool is_signed,
    uint32_t enumerator_byte_size, const DWARFDIE &parent_die) {
  if (!parent_die)
    return 0;

  size_t enumerators_added = 0;

  for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
       die = die.GetSibling()) {
    const dw_tag_t tag = die.Tag();
    if (tag == DW_TAG_enumerator) {
      DWARFAttributes attributes;
      const size_t num_child_attributes = die.GetAttributes(attributes);
      if (num_child_attributes > 0) {
        const char *name = nullptr;
        bool got_value = false;
        int64_t enum_value = 0;
        Declaration decl;

        uint32_t i;
        for (i = 0; i < num_child_attributes; ++i) {
          const dw_attr_t attr = attributes.AttributeAtIndex(i);
          DWARFFormValue form_value;
          if (attributes.ExtractFormValueAtIndex(i, form_value)) {
            switch (attr) {
            case DW_AT_const_value:
              got_value = true;
              if (is_signed)
                enum_value = form_value.Signed();
              else
                enum_value = form_value.Unsigned();
              break;

            case DW_AT_name:
              name = form_value.AsCString();
              break;

            case DW_AT_description:
            default:
            case DW_AT_decl_file:
              decl.SetFile(die.GetCU()->GetFile(form_value.Unsigned()));
              break;
            case DW_AT_decl_line:
              decl.SetLine(form_value.Unsigned());
              break;
            case DW_AT_decl_column:
              decl.SetColumn(form_value.Unsigned());
              break;
            case DW_AT_sibling:
              break;
            }
          }
        }

        if (name && name[0] && got_value) {
          m_ast.AddEnumerationValueToEnumerationType(
              clang_type, decl, name, enum_value, enumerator_byte_size * 8);
          ++enumerators_added;
        }
      }
    }
  }
  return enumerators_added;
}

#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)

class DIEStack {
public:
  void Push(const DWARFDIE &die) { m_dies.push_back(die); }

  void LogDIEs(Log *log) {
    StreamString log_strm;
    const size_t n = m_dies.size();
    log_strm.Printf("DIEStack[%" PRIu64 "]:\n", (uint64_t)n);
    for (size_t i = 0; i < n; i++) {
      std::string qualified_name;
      const DWARFDIE &die = m_dies[i];
      die.GetQualifiedName(qualified_name);
      log_strm.Printf("[%" PRIu64 "] 0x%8.8x: %s name='%s'\n", (uint64_t)i,
                      die.GetOffset(), die.GetTagAsCString(),
                      qualified_name.c_str());
    }
    log->PutCString(log_strm.GetData());
  }
  void Pop() { m_dies.pop_back(); }

  class ScopedPopper {
  public:
    ScopedPopper(DIEStack &die_stack)
        : m_die_stack(die_stack), m_valid(false) {}

    void Push(const DWARFDIE &die) {
      m_valid = true;
      m_die_stack.Push(die);
    }

    ~ScopedPopper() {
      if (m_valid)
        m_die_stack.Pop();
    }

  protected:
    DIEStack &m_die_stack;
    bool m_valid;
  };

protected:
  typedef std::vector<DWARFDIE> Stack;
  Stack m_dies;
};
#endif

Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
                                                      const DWARFDIE &die) {
  DWARFRangeList func_ranges;
  const char *name = nullptr;
  const char *mangled = nullptr;
  int decl_file = 0;
  int decl_line = 0;
  int decl_column = 0;
  int call_file = 0;
  int call_line = 0;
  int call_column = 0;
  DWARFExpression frame_base;

  const dw_tag_t tag = die.Tag();

  if (tag != DW_TAG_subprogram)
    return nullptr;

  if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line,
                               decl_column, call_file, call_line, call_column,
                               &frame_base)) {

    // Union of all ranges in the function DIE (if the function is
    // discontiguous)
    AddressRange func_range;
    lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0);
    lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0);
    if (lowest_func_addr != LLDB_INVALID_ADDRESS &&
        lowest_func_addr <= highest_func_addr) {
      ModuleSP module_sp(die.GetModule());
      func_range.GetBaseAddress().ResolveAddressUsingFileSections(
          lowest_func_addr, module_sp->GetSectionList());
      if (func_range.GetBaseAddress().IsValid())
        func_range.SetByteSize(highest_func_addr - lowest_func_addr);
    }

    if (func_range.GetBaseAddress().IsValid()) {
      Mangled func_name;
      if (mangled)
        func_name.SetValue(ConstString(mangled), true);
      else if ((die.GetParent().Tag() == DW_TAG_compile_unit ||
                die.GetParent().Tag() == DW_TAG_partial_unit) &&
               Language::LanguageIsCPlusPlus(die.GetLanguage()) &&
               !Language::LanguageIsObjC(die.GetLanguage()) && name &&
               strcmp(name, "main") != 0) {
        // If the mangled name is not present in the DWARF, generate the
        // demangled name using the decl context. We skip if the function is
        // "main" as its name is never mangled.
        bool is_static = false;
        bool is_variadic = false;
        bool has_template_params = false;
        unsigned type_quals = 0;
        std::vector<CompilerType> param_types;
        std::vector<clang::ParmVarDecl *> param_decls;
        DWARFDeclContext decl_ctx;
        StreamString sstr;

        die.GetDWARFDeclContext(decl_ctx);
        sstr << decl_ctx.GetQualifiedName();

        clang::DeclContext *containing_decl_ctx =
            GetClangDeclContextContainingDIE(die, nullptr);
        ParseChildParameters(containing_decl_ctx, die, true, is_static,
                             is_variadic, has_template_params, param_types,
                             param_decls, type_quals);
        sstr << "(";
        for (size_t i = 0; i < param_types.size(); i++) {
          if (i > 0)
            sstr << ", ";
          sstr << param_types[i].GetTypeName();
        }
        if (is_variadic)
          sstr << ", ...";
        sstr << ")";
        if (type_quals & clang::Qualifiers::Const)
          sstr << " const";

        func_name.SetValue(ConstString(sstr.GetString()), false);
      } else
        func_name.SetValue(ConstString(name), false);

      FunctionSP func_sp;
      std::unique_ptr<Declaration> decl_up;
      if (decl_file != 0 || decl_line != 0 || decl_column != 0)
        decl_up.reset(new Declaration(die.GetCU()->GetFile(decl_file),
                                      decl_line, decl_column));

      SymbolFileDWARF *dwarf = die.GetDWARF();
      // Supply the type _only_ if it has already been parsed
      Type *func_type = dwarf->GetDIEToType().lookup(die.GetDIE());

      assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED);

      if (dwarf->FixupAddress(func_range.GetBaseAddress())) {
        const user_id_t func_user_id = die.GetID();
        func_sp =
            std::make_shared<Function>(&comp_unit,
                                   func_user_id, // UserID is the DIE offset
                                   func_user_id, func_name, func_type,
                                       func_range); // first address range

        if (func_sp.get() != nullptr) {
          if (frame_base.IsValid())
            func_sp->GetFrameBaseExpression() = frame_base;
          comp_unit.AddFunction(func_sp);
          return func_sp.get();
        }
      }
    }
  }
  return nullptr;
}

bool DWARFASTParserClang::ParseChildMembers(
    const DWARFDIE &parent_die, CompilerType &class_clang_type,
    const LanguageType class_language,
    std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
    std::vector<int> &member_accessibilities,
    std::vector<DWARFDIE> &member_function_dies,
    DelayedPropertyList &delayed_properties, AccessType &default_accessibility,
    bool &is_a_class, ClangASTImporter::LayoutInfo &layout_info) {
  if (!parent_die)
    return false;

  // Get the parent byte size so we can verify any members will fit
  const uint64_t parent_byte_size =
      parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX);
  const uint64_t parent_bit_size =
      parent_byte_size == UINT64_MAX ? UINT64_MAX : parent_byte_size * 8;

  uint32_t member_idx = 0;
  BitfieldInfo last_field_info;

  ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
  ClangASTContext *ast =
      llvm::dyn_cast_or_null<ClangASTContext>(class_clang_type.GetTypeSystem());
  if (ast == nullptr)
    return false;

  for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
       die = die.GetSibling()) {
    dw_tag_t tag = die.Tag();

    switch (tag) {
    case DW_TAG_member:
    case DW_TAG_APPLE_property: {
      DWARFAttributes attributes;
      const size_t num_attributes = die.GetAttributes(attributes);
      if (num_attributes > 0) {
        const char *name = nullptr;
        const char *prop_name = nullptr;
        const char *prop_getter_name = nullptr;
        const char *prop_setter_name = nullptr;
        uint32_t prop_attributes = 0;

        bool is_artificial = false;
        DWARFFormValue encoding_form;
        AccessType accessibility = eAccessNone;
        uint32_t member_byte_offset =
            (parent_die.Tag() == DW_TAG_union_type) ? 0 : UINT32_MAX;
        llvm::Optional<uint64_t> byte_size;
        int64_t bit_offset = 0;
        uint64_t data_bit_offset = UINT64_MAX;
        size_t bit_size = 0;
        bool is_external =
            false; // On DW_TAG_members, this means the member is static
        uint32_t i;
        for (i = 0; i < num_attributes && !is_artificial; ++i) {
          const dw_attr_t attr = attributes.AttributeAtIndex(i);
          DWARFFormValue form_value;
          if (attributes.ExtractFormValueAtIndex(i, form_value)) {
            switch (attr) {
            case DW_AT_name:
              name = form_value.AsCString();
              break;
            case DW_AT_type:
              encoding_form = form_value;
              break;
            case DW_AT_bit_offset:
              bit_offset = form_value.Signed();
              break;
            case DW_AT_bit_size:
              bit_size = form_value.Unsigned();
              break;
            case DW_AT_byte_size:
              byte_size = form_value.Unsigned();
              break;
            case DW_AT_data_bit_offset:
              data_bit_offset = form_value.Unsigned();
              break;
            case DW_AT_data_member_location:
              if (form_value.BlockData()) {
                Value initialValue(0);
                Value memberOffset(0);
                const DWARFDataExtractor &debug_info_data = die.GetData();
                uint32_t block_length = form_value.Unsigned();
                uint32_t block_offset =
                    form_value.BlockData() - debug_info_data.GetDataStart();
                if (DWARFExpression::Evaluate(
                        nullptr, // ExecutionContext *
                        nullptr, // RegisterContext *
                        module_sp,
                        DataExtractor(debug_info_data, block_offset,
                                      block_length),
                        die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr,
                        memberOffset, nullptr)) {
                  member_byte_offset =
                      memberOffset.ResolveValue(nullptr).UInt();
                }
              } else {
                // With DWARF 3 and later, if the value is an integer constant,
                // this form value is the offset in bytes from the beginning of
                // the containing entity.
                member_byte_offset = form_value.Unsigned();
              }
              break;

            case DW_AT_accessibility:
              accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
              break;
            case DW_AT_artificial:
              is_artificial = form_value.Boolean();
              break;
            case DW_AT_APPLE_property_name:
              prop_name = form_value.AsCString();
              break;
            case DW_AT_APPLE_property_getter:
              prop_getter_name = form_value.AsCString();
              break;
            case DW_AT_APPLE_property_setter:
              prop_setter_name = form_value.AsCString();
              break;
            case DW_AT_APPLE_property_attribute:
              prop_attributes = form_value.Unsigned();
              break;
            case DW_AT_external:
              is_external = form_value.Boolean();
              break;

            default:
            case DW_AT_declaration:
            case DW_AT_description:
            case DW_AT_mutable:
            case DW_AT_visibility:
            case DW_AT_sibling:
              break;
            }
          }
        }

        if (prop_name) {
          ConstString fixed_getter;
          ConstString fixed_setter;

          // Check if the property getter/setter were provided as full names.
          // We want basenames, so we extract them.

          if (prop_getter_name && prop_getter_name[0] == '-') {
            ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
            prop_getter_name = prop_getter_method.GetSelector().GetCString();
          }

          if (prop_setter_name && prop_setter_name[0] == '-') {
            ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true);
            prop_setter_name = prop_setter_method.GetSelector().GetCString();
          }

          // If the names haven't been provided, they need to be filled in.

          if (!prop_getter_name) {
            prop_getter_name = prop_name;
          }
          if (!prop_setter_name && prop_name[0] &&
              !(prop_attributes & DW_APPLE_PROPERTY_readonly)) {
            StreamString ss;

            ss.Printf("set%c%s:", toupper(prop_name[0]), &prop_name[1]);

            fixed_setter.SetString(ss.GetString());
            prop_setter_name = fixed_setter.GetCString();
          }
        }

        // Clang has a DWARF generation bug where sometimes it represents
        // fields that are references with bad byte size and bit size/offset
        // information such as:
        //
        //  DW_AT_byte_size( 0x00 )
        //  DW_AT_bit_size( 0x40 )
        //  DW_AT_bit_offset( 0xffffffffffffffc0 )
        //
        // So check the bit offset to make sure it is sane, and if the values
        // are not sane, remove them. If we don't do this then we will end up
        // with a crash if we try to use this type in an expression when clang
        // becomes unhappy with its recycled debug info.

        if (byte_size.getValueOr(0) == 0 && bit_offset < 0) {
          bit_size = 0;
          bit_offset = 0;
        }

        // FIXME: Make Clang ignore Objective-C accessibility for expressions
        if (class_language == eLanguageTypeObjC ||
            class_language == eLanguageTypeObjC_plus_plus)
          accessibility = eAccessNone;

        // Handle static members
        if (is_external && member_byte_offset == UINT32_MAX) {
          Type *var_type = die.ResolveTypeUID(encoding_form.Reference());

          if (var_type) {
            if (accessibility == eAccessNone)
              accessibility = eAccessPublic;
            ClangASTContext::AddVariableToRecordType(
                class_clang_type, name, var_type->GetLayoutCompilerType(),
                accessibility);
          }
          break;
        }

        if (!is_artificial) {
          Type *member_type = die.ResolveTypeUID(encoding_form.Reference());

          clang::FieldDecl *field_decl = nullptr;
          if (tag == DW_TAG_member) {
            if (member_type) {
              if (accessibility == eAccessNone)
                accessibility = default_accessibility;
              member_accessibilities.push_back(accessibility);

              uint64_t field_bit_offset =
                  (member_byte_offset == UINT32_MAX ? 0
                                                    : (member_byte_offset * 8));
              if (bit_size > 0) {

                BitfieldInfo this_field_info;
                this_field_info.bit_offset = field_bit_offset;
                this_field_info.bit_size = bit_size;

                /////////////////////////////////////////////////////////////
                // How to locate a field given the DWARF debug information
                //
                // AT_byte_size indicates the size of the word in which the bit
                // offset must be interpreted.
                //
                // AT_data_member_location indicates the byte offset of the
                // word from the base address of the structure.
                //
                // AT_bit_offset indicates how many bits into the word
                // (according to the host endianness) the low-order bit of the
                // field starts.  AT_bit_offset can be negative.
                //
                // AT_bit_size indicates the size of the field in bits.
                /////////////////////////////////////////////////////////////

                if (data_bit_offset != UINT64_MAX) {
                  this_field_info.bit_offset = data_bit_offset;
                } else {
                  if (!byte_size)
                    byte_size = member_type->GetByteSize();

                  ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
                  if (objfile->GetByteOrder() == eByteOrderLittle) {
                    this_field_info.bit_offset += byte_size.getValueOr(0) * 8;
                    this_field_info.bit_offset -= (bit_offset + bit_size);
                  } else {
                    this_field_info.bit_offset += bit_offset;
                  }
                }

                if ((this_field_info.bit_offset >= parent_bit_size) ||
                    !last_field_info.NextBitfieldOffsetIsValid(
                        this_field_info.bit_offset)) {
                  ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
                  objfile->GetModule()->ReportWarning(
                      "0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid "
                      "bit offset (0x%8.8" PRIx64
                      ") member will be ignored. Please file a bug against the "
                      "compiler and include the preprocessed output for %s\n",
                      die.GetID(), DW_TAG_value_to_name(tag), name,
                      this_field_info.bit_offset,
                      GetUnitName(parent_die).c_str());
                  this_field_info.Clear();
                  continue;
                }

                // Update the field bit offset we will report for layout
                field_bit_offset = this_field_info.bit_offset;

                // If the member to be emitted did not start on a character
                // boundary and there is empty space between the last field and
                // this one, then we need to emit an anonymous member filling
                // up the space up to its start.  There are three cases here:
                //
                // 1 If the previous member ended on a character boundary, then
                // we can emit an
                //   anonymous member starting at the most recent character
                //   boundary.
                //
                // 2 If the previous member did not end on a character boundary
                // and the distance
                //   from the end of the previous member to the current member
                //   is less than a
                //   word width, then we can emit an anonymous member starting
                //   right after the
                //   previous member and right before this member.
                //
                // 3 If the previous member did not end on a character boundary
                // and the distance
                //   from the end of the previous member to the current member
                //   is greater than
                //   or equal a word width, then we act as in Case 1.

                const uint64_t character_width = 8;
                const uint64_t word_width = 32;

                // Objective-C has invalid DW_AT_bit_offset values in older
                // versions of clang, so we have to be careful and only insert
                // unnamed bitfields if we have a new enough clang.
                bool detect_unnamed_bitfields = true;

                if (class_language == eLanguageTypeObjC ||
                    class_language == eLanguageTypeObjC_plus_plus)
                  detect_unnamed_bitfields =
                      die.GetCU()->Supports_unnamed_objc_bitfields();

                if (detect_unnamed_bitfields) {
                  BitfieldInfo anon_field_info;

                  if ((this_field_info.bit_offset % character_width) !=
                      0) // not char aligned
                  {
                    uint64_t last_field_end = 0;

                    if (last_field_info.IsValid())
                      last_field_end =
                          last_field_info.bit_offset + last_field_info.bit_size;

                    if (this_field_info.bit_offset != last_field_end) {
                      if (((last_field_end % character_width) == 0) || // case 1
                          (this_field_info.bit_offset - last_field_end >=
                           word_width)) // case 3
                      {
                        anon_field_info.bit_size =
                            this_field_info.bit_offset % character_width;
                        anon_field_info.bit_offset =
                            this_field_info.bit_offset -
                            anon_field_info.bit_size;
                      } else // case 2
                      {
                        anon_field_info.bit_size =
                            this_field_info.bit_offset - last_field_end;
                        anon_field_info.bit_offset = last_field_end;
                      }
                    }
                  }

                  if (anon_field_info.IsValid()) {
                    clang::FieldDecl *unnamed_bitfield_decl =
                        ClangASTContext::AddFieldToRecordType(
                            class_clang_type, llvm::StringRef(),
                            m_ast.GetBuiltinTypeForEncodingAndBitSize(
                                eEncodingSint, word_width),
                            accessibility, anon_field_info.bit_size);

                    layout_info.field_offsets.insert(std::make_pair(
                        unnamed_bitfield_decl, anon_field_info.bit_offset));
                  }
                }
                last_field_info = this_field_info;
              } else {
                last_field_info.Clear();
              }

              CompilerType member_clang_type =
                  member_type->GetLayoutCompilerType();
              if (!member_clang_type.IsCompleteType())
                member_clang_type.GetCompleteType();

              {
                // Older versions of clang emit array[0] and array[1] in the
                // same way (<rdar://problem/12566646>). If the current field
                // is at the end of the structure, then there is definitely no
                // room for extra elements and we override the type to
                // array[0].

                CompilerType member_array_element_type;
                uint64_t member_array_size;
                bool member_array_is_incomplete;

                if (member_clang_type.IsArrayType(
                        &member_array_element_type, &member_array_size,
                        &member_array_is_incomplete) &&
                    !member_array_is_incomplete) {
                  uint64_t parent_byte_size =
                      parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size,
                                                             UINT64_MAX);

                  if (member_byte_offset >= parent_byte_size) {
                    if (member_array_size != 1 &&
                        (member_array_size != 0 ||
                         member_byte_offset > parent_byte_size)) {
                      module_sp->ReportError(
                          "0x%8.8" PRIx64
                          ": DW_TAG_member '%s' refers to type 0x%8.8x"
                          " which extends beyond the bounds of 0x%8.8" PRIx64,
                          die.GetID(), name,
                          encoding_form.Reference().GetOffset(),
                          parent_die.GetID());
                    }

                    member_clang_type = m_ast.CreateArrayType(
                        member_array_element_type, 0, false);
                  }
                }
              }

              if (ClangASTContext::IsCXXClassType(member_clang_type) &&
                  !member_clang_type.GetCompleteType()) {
                if (die.GetCU()->GetProducer() == eProducerClang)
                  module_sp->ReportError(
                      "DWARF DIE at 0x%8.8x (class %s) has a member variable "
                      "0x%8.8x (%s) whose type is a forward declaration, not a "
                      "complete definition.\nTry compiling the source file "
                      "with -fstandalone-debug",
                      parent_die.GetOffset(), parent_die.GetName(),
                      die.GetOffset(), name);
                else
                  module_sp->ReportError(
                      "DWARF DIE at 0x%8.8x (class %s) has a member variable "
                      "0x%8.8x (%s) whose type is a forward declaration, not a "
                      "complete definition.\nPlease file a bug against the "
                      "compiler and include the preprocessed output for %s",
                      parent_die.GetOffset(), parent_die.GetName(),
                      die.GetOffset(), name, GetUnitName(parent_die).c_str());
                // We have no choice other than to pretend that the member
                // class is complete. If we don't do this, clang will crash
                // when trying to layout the class. Since we provide layout
                // assistance, all ivars in this class and other classes will
                // be fine, this is the best we can do short of crashing.
                if (ClangASTContext::StartTagDeclarationDefinition(
                        member_clang_type)) {
                  ClangASTContext::CompleteTagDeclarationDefinition(
                      member_clang_type);
                } else {
                  module_sp->ReportError(
                      "DWARF DIE at 0x%8.8x (class %s) has a member variable "
                      "0x%8.8x (%s) whose type claims to be a C++ class but we "
                      "were not able to start its definition.\nPlease file a "
                      "bug and attach the file at the start of this error "
                      "message",
                      parent_die.GetOffset(), parent_die.GetName(),
                      die.GetOffset(), name);
                }
              }

              field_decl = ClangASTContext::AddFieldToRecordType(
                  class_clang_type, name, member_clang_type, accessibility,
                  bit_size);

              m_ast.SetMetadataAsUserID(field_decl, die.GetID());

              layout_info.field_offsets.insert(
                  std::make_pair(field_decl, field_bit_offset));
            } else {
              if (name)
                module_sp->ReportError(
                    "0x%8.8" PRIx64
                    ": DW_TAG_member '%s' refers to type 0x%8.8x"
                    " which was unable to be parsed",
                    die.GetID(), name, encoding_form.Reference().GetOffset());
              else
                module_sp->ReportError(
                    "0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8x"
                    " which was unable to be parsed",
                    die.GetID(), encoding_form.Reference().GetOffset());
            }
          }

          if (prop_name != nullptr && member_type) {
            clang::ObjCIvarDecl *ivar_decl = nullptr;

            if (field_decl) {
              ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl);
              assert(ivar_decl != nullptr);
            }

            ClangASTMetadata metadata;
            metadata.SetUserID(die.GetID());
            delayed_properties.push_back(DelayedAddObjCClassProperty(
                class_clang_type, prop_name,
                member_type->GetLayoutCompilerType(), ivar_decl,
                prop_setter_name, prop_getter_name, prop_attributes,
                &metadata));

            if (ivar_decl)
              m_ast.SetMetadataAsUserID(ivar_decl, die.GetID());
          }
        }
      }
      ++member_idx;
    } break;

    case DW_TAG_subprogram:
      // Let the type parsing code handle this one for us.
      member_function_dies.push_back(die);
      break;

    case DW_TAG_inheritance: {
      is_a_class = true;
      if (default_accessibility == eAccessNone)
        default_accessibility = eAccessPrivate;
      // TODO: implement DW_TAG_inheritance type parsing
      DWARFAttributes attributes;
      const size_t num_attributes = die.GetAttributes(attributes);
      if (num_attributes > 0) {
        DWARFFormValue encoding_form;
        AccessType accessibility = default_accessibility;
        bool is_virtual = false;
        bool is_base_of_class = true;
        off_t member_byte_offset = 0;
        uint32_t i;
        for (i = 0; i < num_attributes; ++i) {
          const dw_attr_t attr = attributes.AttributeAtIndex(i);
          DWARFFormValue form_value;
          if (attributes.ExtractFormValueAtIndex(i, form_value)) {
            switch (attr) {
            case DW_AT_type:
              encoding_form = form_value;
              break;
            case DW_AT_data_member_location:
              if (form_value.BlockData()) {
                Value initialValue(0);
                Value memberOffset(0);
                const DWARFDataExtractor &debug_info_data = die.GetData();
                uint32_t block_length = form_value.Unsigned();
                uint32_t block_offset =
                    form_value.BlockData() - debug_info_data.GetDataStart();
                if (DWARFExpression::Evaluate(
                        nullptr, nullptr, module_sp,
                        DataExtractor(debug_info_data, block_offset,
                                      block_length),
                        die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr,
                        memberOffset, nullptr)) {
                  member_byte_offset =
                      memberOffset.ResolveValue(nullptr).UInt();
                }
              } else {
                // With DWARF 3 and later, if the value is an integer constant,
                // this form value is the offset in bytes from the beginning of
                // the containing entity.
                member_byte_offset = form_value.Unsigned();
              }
              break;

            case DW_AT_accessibility:
              accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
              break;

            case DW_AT_virtuality:
              is_virtual = form_value.Boolean();
              break;

            case DW_AT_sibling:
              break;

            default:
              break;
            }
          }
        }

        Type *base_class_type = die.ResolveTypeUID(encoding_form.Reference());
        if (base_class_type == nullptr) {
          module_sp->ReportError("0x%8.8x: DW_TAG_inheritance failed to "
                                 "resolve the base class at 0x%8.8x"
                                 " from enclosing type 0x%8.8x. \nPlease file "
                                 "a bug and attach the file at the start of "
                                 "this error message",
                                 die.GetOffset(),
                                 encoding_form.Reference().GetOffset(),
                                 parent_die.GetOffset());
          break;
        }

        CompilerType base_class_clang_type =
            base_class_type->GetFullCompilerType();
        assert(base_class_clang_type);
        if (class_language == eLanguageTypeObjC) {
          ast->SetObjCSuperClass(class_clang_type, base_class_clang_type);
        } else {
          std::unique_ptr<clang::CXXBaseSpecifier> result =
              ast->CreateBaseClassSpecifier(
                  base_class_clang_type.GetOpaqueQualType(), accessibility,
                  is_virtual, is_base_of_class);
          if (!result)
            break;

          base_classes.push_back(std::move(result));

          if (is_virtual) {
            // Do not specify any offset for virtual inheritance. The DWARF
            // produced by clang doesn't give us a constant offset, but gives
            // us a DWARF expressions that requires an actual object in memory.
            // the DW_AT_data_member_location for a virtual base class looks
            // like:
            //      DW_AT_data_member_location( DW_OP_dup, DW_OP_deref,
            //      DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref,
            //      DW_OP_plus )
            // Given this, there is really no valid response we can give to
            // clang for virtual base class offsets, and this should eventually
            // be removed from LayoutRecordType() in the external
            // AST source in clang.
          } else {
            layout_info.base_offsets.insert(std::make_pair(
                ast->GetAsCXXRecordDecl(
                    base_class_clang_type.GetOpaqueQualType()),
                clang::CharUnits::fromQuantity(member_byte_offset)));
          }
        }
      }
    } break;

    default:
      break;
    }
  }

  return true;
}

size_t DWARFASTParserClang::ParseChildParameters(
    clang::DeclContext *containing_decl_ctx, const DWARFDIE &parent_die,
    bool skip_artificial, bool &is_static, bool &is_variadic,
    bool &has_template_params, std::vector<CompilerType> &function_param_types,
    std::vector<clang::ParmVarDecl *> &function_param_decls,
    unsigned &type_quals) {
  if (!parent_die)
    return 0;

  size_t arg_idx = 0;
  for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
       die = die.GetSibling()) {
    const dw_tag_t tag = die.Tag();
    switch (tag) {
    case DW_TAG_formal_parameter: {
      DWARFAttributes attributes;
      const size_t num_attributes = die.GetAttributes(attributes);
      if (num_attributes > 0) {
        const char *name = nullptr;
        DWARFFormValue param_type_die_form;
        bool is_artificial = false;
        // one of None, Auto, Register, Extern, Static, PrivateExtern

        clang::StorageClass storage = clang::SC_None;
        uint32_t i;
        for (i = 0; i < num_attributes; ++i) {
          const dw_attr_t attr = attributes.AttributeAtIndex(i);
          DWARFFormValue form_value;
          if (attributes.ExtractFormValueAtIndex(i, form_value)) {
            switch (attr) {
            case DW_AT_name:
              name = form_value.AsCString();
              break;
            case DW_AT_type:
              param_type_die_form = form_value;
              break;
            case DW_AT_artificial:
              is_artificial = form_value.Boolean();
              break;
            case DW_AT_location:
            case DW_AT_const_value:
            case DW_AT_default_value:
            case DW_AT_description:
            case DW_AT_endianity:
            case DW_AT_is_optional:
            case DW_AT_segment:
            case DW_AT_variable_parameter:
            default:
            case DW_AT_abstract_origin:
            case DW_AT_sibling:
              break;
            }
          }
        }

        bool skip = false;
        if (skip_artificial && is_artificial) {
          // In order to determine if a C++ member function is "const" we
          // have to look at the const-ness of "this"...
          if (arg_idx == 0 &&
              DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()) &&
              // Often times compilers omit the "this" name for the
              // specification DIEs, so we can't rely upon the name being in
              // the formal parameter DIE...
              (name == nullptr || ::strcmp(name, "this") == 0)) {
            Type *this_type =
                die.ResolveTypeUID(param_type_die_form.Reference());
            if (this_type) {
              uint32_t encoding_mask = this_type->GetEncodingMask();
              if (encoding_mask & Type::eEncodingIsPointerUID) {
                is_static = false;

                if (encoding_mask & (1u << Type::eEncodingIsConstUID))
                  type_quals |= clang::Qualifiers::Const;
                if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
                  type_quals |= clang::Qualifiers::Volatile;
              }
            }
          }
          skip = true;
        }

        if (!skip) {
          Type *type = die.ResolveTypeUID(param_type_die_form.Reference());
          if (type) {
            function_param_types.push_back(type->GetForwardCompilerType());

            clang::ParmVarDecl *param_var_decl =
                m_ast.CreateParameterDeclaration(containing_decl_ctx, name,
                                                 type->GetForwardCompilerType(),
                                                 storage);
            assert(param_var_decl);
            function_param_decls.push_back(param_var_decl);

            m_ast.SetMetadataAsUserID(param_var_decl, die.GetID());
          }
        }
      }
      arg_idx++;
    } break;

    case DW_TAG_unspecified_parameters:
      is_variadic = true;
      break;

    case DW_TAG_template_type_parameter:
    case DW_TAG_template_value_parameter:
    case DW_TAG_GNU_template_parameter_pack:
      // The one caller of this was never using the template_param_infos, and
      // the local variable was taking up a large amount of stack space in
      // SymbolFileDWARF::ParseType() so this was removed. If we ever need the
      // template params back, we can add them back.
      // ParseTemplateDIE (dwarf_cu, die, template_param_infos);
      has_template_params = true;
      break;

    default:
      break;
    }
  }
  return arg_idx;
}

llvm::Optional<SymbolFile::ArrayInfo>
DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die,
                                    const ExecutionContext *exe_ctx) {
  SymbolFile::ArrayInfo array_info;
  if (!parent_die)
    return llvm::None;

  for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
       die = die.GetSibling()) {
    const dw_tag_t tag = die.Tag();
    switch (tag) {
    case DW_TAG_subrange_type: {
      DWARFAttributes attributes;
      const size_t num_child_attributes = die.GetAttributes(attributes);
      if (num_child_attributes > 0) {
        uint64_t num_elements = 0;
        uint64_t lower_bound = 0;
        uint64_t upper_bound = 0;
        bool upper_bound_valid = false;
        uint32_t i;
        for (i = 0; i < num_child_attributes; ++i) {
          const dw_attr_t attr = attributes.AttributeAtIndex(i);
          DWARFFormValue form_value;
          if (attributes.ExtractFormValueAtIndex(i, form_value)) {
            switch (attr) {
            case DW_AT_name:
              break;

            case DW_AT_count:
              if (DWARFDIE var_die = die.GetReferencedDIE(DW_AT_count)) {
                if (var_die.Tag() == DW_TAG_variable)
                  if (exe_ctx) {
                    if (auto frame = exe_ctx->GetFrameSP()) {
                      Status error;
                      lldb::VariableSP var_sp;
                      auto valobj_sp = frame->GetValueForVariableExpressionPath(
                          var_die.GetName(), eNoDynamicValues, 0, var_sp,
                          error);
                      if (valobj_sp) {
                        num_elements = valobj_sp->GetValueAsUnsigned(0);
                        break;
                      }
                    }
                  }
              } else
                num_elements = form_value.Unsigned();
              break;

            case DW_AT_bit_stride:
              array_info.bit_stride = form_value.Unsigned();
              break;

            case DW_AT_byte_stride:
              array_info.byte_stride = form_value.Unsigned();
              break;

            case DW_AT_lower_bound:
              lower_bound = form_value.Unsigned();
              break;

            case DW_AT_upper_bound:
              upper_bound_valid = true;
              upper_bound = form_value.Unsigned();
              break;

            default:
            case DW_AT_abstract_origin:
            case DW_AT_accessibility:
            case DW_AT_allocated:
            case DW_AT_associated:
            case DW_AT_data_location:
            case DW_AT_declaration:
            case DW_AT_description:
            case DW_AT_sibling:
            case DW_AT_threads_scaled:
            case DW_AT_type:
            case DW_AT_visibility:
              break;
            }
          }
        }

        if (num_elements == 0) {
          if (upper_bound_valid && upper_bound >= lower_bound)
            num_elements = upper_bound - lower_bound + 1;
        }

        array_info.element_orders.push_back(num_elements);
      }
    } break;
    default:
      break;
    }
  }
  return array_info;
}

Type *DWARFASTParserClang::GetTypeForDIE(const DWARFDIE &die) {
  if (die) {
    SymbolFileDWARF *dwarf = die.GetDWARF();
    DWARFAttributes attributes;
    const size_t num_attributes = die.GetAttributes(attributes);
    if (num_attributes > 0) {
      DWARFFormValue type_die_form;
      for (size_t i = 0; i < num_attributes; ++i) {
        dw_attr_t attr = attributes.AttributeAtIndex(i);
        DWARFFormValue form_value;

        if (attr == DW_AT_type &&
            attributes.ExtractFormValueAtIndex(i, form_value))
          return dwarf->ResolveTypeUID(form_value.Reference(), true);
      }
    }
  }

  return nullptr;
}

clang::Decl *DWARFASTParserClang::GetClangDeclForDIE(const DWARFDIE &die) {
  if (!die)
    return nullptr;

  switch (die.Tag()) {
  case DW_TAG_variable:
  case DW_TAG_constant:
  case DW_TAG_formal_parameter:
  case DW_TAG_imported_declaration:
  case DW_TAG_imported_module:
    break;
  default:
    return nullptr;
  }

  DIEToDeclMap::iterator cache_pos = m_die_to_decl.find(die.GetDIE());
  if (cache_pos != m_die_to_decl.end())
    return cache_pos->second;

  if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification)) {
    clang::Decl *decl = GetClangDeclForDIE(spec_die);
    m_die_to_decl[die.GetDIE()] = decl;
    m_decl_to_die[decl].insert(die.GetDIE());
    return decl;
  }

  if (DWARFDIE abstract_origin_die =
          die.GetReferencedDIE(DW_AT_abstract_origin)) {
    clang::Decl *decl = GetClangDeclForDIE(abstract_origin_die);
    m_die_to_decl[die.GetDIE()] = decl;
    m_decl_to_die[decl].insert(die.GetDIE());
    return decl;
  }

  clang::Decl *decl = nullptr;
  switch (die.Tag()) {
  case DW_TAG_variable:
  case DW_TAG_constant:
  case DW_TAG_formal_parameter: {
    SymbolFileDWARF *dwarf = die.GetDWARF();
    Type *type = GetTypeForDIE(die);
    if (dwarf && type) {
      const char *name = die.GetName();
      clang::DeclContext *decl_context =
          ClangASTContext::DeclContextGetAsDeclContext(
              dwarf->GetDeclContextContainingUID(die.GetID()));
      decl = m_ast.CreateVariableDeclaration(
          decl_context, name,
          ClangUtil::GetQualType(type->GetForwardCompilerType()));
    }
    break;
  }
  case DW_TAG_imported_declaration: {
    SymbolFileDWARF *dwarf = die.GetDWARF();
    DWARFDIE imported_uid = die.GetAttributeValueAsReferenceDIE(DW_AT_import);
    if (imported_uid) {
      CompilerDecl imported_decl = imported_uid.GetDecl();
      if (imported_decl) {
        clang::DeclContext *decl_context =
            ClangASTContext::DeclContextGetAsDeclContext(
                dwarf->GetDeclContextContainingUID(die.GetID()));
        if (clang::NamedDecl *clang_imported_decl =
                llvm::dyn_cast<clang::NamedDecl>(
                    (clang::Decl *)imported_decl.GetOpaqueDecl()))
          decl =
              m_ast.CreateUsingDeclaration(decl_context, clang_imported_decl);
      }
    }
    break;
  }
  case DW_TAG_imported_module: {
    SymbolFileDWARF *dwarf = die.GetDWARF();
    DWARFDIE imported_uid = die.GetAttributeValueAsReferenceDIE(DW_AT_import);

    if (imported_uid) {
      CompilerDeclContext imported_decl_ctx = imported_uid.GetDeclContext();
      if (imported_decl_ctx) {
        clang::DeclContext *decl_context =
            ClangASTContext::DeclContextGetAsDeclContext(
                dwarf->GetDeclContextContainingUID(die.GetID()));
        if (clang::NamespaceDecl *ns_decl =
                ClangASTContext::DeclContextGetAsNamespaceDecl(
                    imported_decl_ctx))
          decl = m_ast.CreateUsingDirectiveDeclaration(decl_context, ns_decl);
      }
    }
    break;
  }
  default:
    break;
  }

  m_die_to_decl[die.GetDIE()] = decl;
  m_decl_to_die[decl].insert(die.GetDIE());

  return decl;
}

clang::DeclContext *
DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) {
  if (die) {
    clang::DeclContext *decl_ctx = GetCachedClangDeclContextForDIE(die);
    if (decl_ctx)
      return decl_ctx;

    bool try_parsing_type = true;
    switch (die.Tag()) {
    case DW_TAG_compile_unit:
    case DW_TAG_partial_unit:
      decl_ctx = m_ast.GetTranslationUnitDecl();
      try_parsing_type = false;
      break;

    case DW_TAG_namespace:
      decl_ctx = ResolveNamespaceDIE(die);
      try_parsing_type = false;
      break;

    case DW_TAG_lexical_block:
      decl_ctx = GetDeclContextForBlock(die);
      try_parsing_type = false;
      break;

    default:
      break;
    }

    if (decl_ctx == nullptr && try_parsing_type) {
      Type *type = die.GetDWARF()->ResolveType(die);
      if (type)
        decl_ctx = GetCachedClangDeclContextForDIE(die);
    }

    if (decl_ctx) {
      LinkDeclContextToDIE(decl_ctx, die);
      return decl_ctx;
    }
  }
  return nullptr;
}

static bool IsSubroutine(const DWARFDIE &die) {
  switch (die.Tag()) {
  case DW_TAG_subprogram:
  case DW_TAG_inlined_subroutine:
    return true;
  default:
    return false;
  }
}

static DWARFDIE GetContainingFunctionWithAbstractOrigin(const DWARFDIE &die) {
  for (DWARFDIE candidate = die; candidate; candidate = candidate.GetParent()) {
    if (IsSubroutine(candidate)) {
      if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) {
        return candidate;
      } else {
        return DWARFDIE();
      }
    }
  }
  assert(0 && "Shouldn't call GetContainingFunctionWithAbstractOrigin on "
              "something not in a function");
  return DWARFDIE();
}

static DWARFDIE FindAnyChildWithAbstractOrigin(const DWARFDIE &context) {
  for (DWARFDIE candidate = context.GetFirstChild(); candidate.IsValid();
       candidate = candidate.GetSibling()) {
    if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) {
      return candidate;
    }
  }
  return DWARFDIE();
}

static DWARFDIE FindFirstChildWithAbstractOrigin(const DWARFDIE &block,
                                                 const DWARFDIE &function) {
  assert(IsSubroutine(function));
  for (DWARFDIE context = block; context != function.GetParent();
       context = context.GetParent()) {
    assert(!IsSubroutine(context) || context == function);
    if (DWARFDIE child = FindAnyChildWithAbstractOrigin(context)) {
      return child;
    }
  }
  return DWARFDIE();
}

clang::DeclContext *
DWARFASTParserClang::GetDeclContextForBlock(const DWARFDIE &die) {
  assert(die.Tag() == DW_TAG_lexical_block);
  DWARFDIE containing_function_with_abstract_origin =
      GetContainingFunctionWithAbstractOrigin(die);
  if (!containing_function_with_abstract_origin) {
    return (clang::DeclContext *)ResolveBlockDIE(die);
  }
  DWARFDIE child = FindFirstChildWithAbstractOrigin(
      die, containing_function_with_abstract_origin);
  CompilerDeclContext decl_context =
      GetDeclContextContainingUIDFromDWARF(child);
  return (clang::DeclContext *)decl_context.GetOpaqueDeclContext();
}

clang::BlockDecl *DWARFASTParserClang::ResolveBlockDIE(const DWARFDIE &die) {
  if (die && die.Tag() == DW_TAG_lexical_block) {
    clang::BlockDecl *decl =
        llvm::cast_or_null<clang::BlockDecl>(m_die_to_decl_ctx[die.GetDIE()]);

    if (!decl) {
      DWARFDIE decl_context_die;
      clang::DeclContext *decl_context =
          GetClangDeclContextContainingDIE(die, &decl_context_die);
      decl = m_ast.CreateBlockDeclaration(decl_context);

      if (decl)
        LinkDeclContextToDIE((clang::DeclContext *)decl, die);
    }

    return decl;
  }
  return nullptr;
}

clang::NamespaceDecl *
DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) {
  if (die && die.Tag() == DW_TAG_namespace) {
    // See if we already parsed this namespace DIE and associated it with a
    // uniqued namespace declaration
    clang::NamespaceDecl *namespace_decl =
        static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die.GetDIE()]);
    if (namespace_decl)
      return namespace_decl;
    else {
      const char *namespace_name = die.GetName();
      clang::DeclContext *containing_decl_ctx =
          GetClangDeclContextContainingDIE(die, nullptr);
      bool is_inline =
          die.GetAttributeValueAsUnsigned(DW_AT_export_symbols, 0) != 0;

      namespace_decl = m_ast.GetUniqueNamespaceDeclaration(
          namespace_name, containing_decl_ctx, is_inline);
      Log *log =
          nullptr; // (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
      if (log) {
        SymbolFileDWARF *dwarf = die.GetDWARF();
        if (namespace_name) {
          dwarf->GetObjectFile()->GetModule()->LogMessage(
              log, "ASTContext => %p: 0x%8.8" PRIx64
                   ": DW_TAG_namespace with DW_AT_name(\"%s\") => "
                   "clang::NamespaceDecl *%p (original = %p)",
              static_cast<void *>(m_ast.getASTContext()), die.GetID(),
              namespace_name, static_cast<void *>(namespace_decl),
              static_cast<void *>(namespace_decl->getOriginalNamespace()));
        } else {
          dwarf->GetObjectFile()->GetModule()->LogMessage(
              log, "ASTContext => %p: 0x%8.8" PRIx64
                   ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p "
                   "(original = %p)",
              static_cast<void *>(m_ast.getASTContext()), die.GetID(),
              static_cast<void *>(namespace_decl),
              static_cast<void *>(namespace_decl->getOriginalNamespace()));
        }
      }

      if (namespace_decl)
        LinkDeclContextToDIE((clang::DeclContext *)namespace_decl, die);
      return namespace_decl;
    }
  }
  return nullptr;
}

clang::DeclContext *DWARFASTParserClang::GetClangDeclContextContainingDIE(
    const DWARFDIE &die, DWARFDIE *decl_ctx_die_copy) {
  SymbolFileDWARF *dwarf = die.GetDWARF();

  DWARFDIE decl_ctx_die = dwarf->GetDeclContextDIEContainingDIE(die);

  if (decl_ctx_die_copy)
    *decl_ctx_die_copy = decl_ctx_die;

  if (decl_ctx_die) {
    clang::DeclContext *clang_decl_ctx =
        GetClangDeclContextForDIE(decl_ctx_die);
    if (clang_decl_ctx)
      return clang_decl_ctx;
  }
  return m_ast.GetTranslationUnitDecl();
}

clang::DeclContext *
DWARFASTParserClang::GetCachedClangDeclContextForDIE(const DWARFDIE &die) {
  if (die) {
    DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die.GetDIE());
    if (pos != m_die_to_decl_ctx.end())
      return pos->second;
  }
  return nullptr;
}

void DWARFASTParserClang::LinkDeclContextToDIE(clang::DeclContext *decl_ctx,
                                               const DWARFDIE &die) {
  m_die_to_decl_ctx[die.GetDIE()] = decl_ctx;
  // There can be many DIEs for a single decl context
  // m_decl_ctx_to_die[decl_ctx].insert(die.GetDIE());
  m_decl_ctx_to_die.insert(std::make_pair(decl_ctx, die));
}

bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
    const DWARFDIE &src_class_die, const DWARFDIE &dst_class_die,
    lldb_private::Type *class_type, std::vector<DWARFDIE> &failures) {
  if (!class_type || !src_class_die || !dst_class_die)
    return false;
  if (src_class_die.Tag() != dst_class_die.Tag())
    return false;

  // We need to complete the class type so we can get all of the method types
  // parsed so we can then unique those types to their equivalent counterparts
  // in "dst_cu" and "dst_class_die"
  class_type->GetFullCompilerType();

  DWARFDIE src_die;
  DWARFDIE dst_die;
  UniqueCStringMap<DWARFDIE> src_name_to_die;
  UniqueCStringMap<DWARFDIE> dst_name_to_die;
  UniqueCStringMap<DWARFDIE> src_name_to_die_artificial;
  UniqueCStringMap<DWARFDIE> dst_name_to_die_artificial;
  for (src_die = src_class_die.GetFirstChild(); src_die.IsValid();
       src_die = src_die.GetSibling()) {
    if (src_die.Tag() == DW_TAG_subprogram) {
      // Make sure this is a declaration and not a concrete instance by looking
      // for DW_AT_declaration set to 1. Sometimes concrete function instances
      // are placed inside the class definitions and shouldn't be included in
      // the list of things are are tracking here.
      if (src_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
        const char *src_name = src_die.GetMangledName();
        if (src_name) {
          ConstString src_const_name(src_name);
          if (src_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
            src_name_to_die_artificial.Append(src_const_name, src_die);
          else
            src_name_to_die.Append(src_const_name, src_die);
        }
      }
    }
  }
  for (dst_die = dst_class_die.GetFirstChild(); dst_die.IsValid();
       dst_die = dst_die.GetSibling()) {
    if (dst_die.Tag() == DW_TAG_subprogram) {
      // Make sure this is a declaration and not a concrete instance by looking
      // for DW_AT_declaration set to 1. Sometimes concrete function instances
      // are placed inside the class definitions and shouldn't be included in
      // the list of things are are tracking here.
      if (dst_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
        const char *dst_name = dst_die.GetMangledName();
        if (dst_name) {
          ConstString dst_const_name(dst_name);
          if (dst_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
            dst_name_to_die_artificial.Append(dst_const_name, dst_die);
          else
            dst_name_to_die.Append(dst_const_name, dst_die);
        }
      }
    }
  }
  const uint32_t src_size = src_name_to_die.GetSize();
  const uint32_t dst_size = dst_name_to_die.GetSize();
  Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO |
                      // DWARF_LOG_TYPE_COMPLETION));

  // Is everything kosher so we can go through the members at top speed?
  bool fast_path = true;

  if (src_size != dst_size) {
    if (src_size != 0 && dst_size != 0) {
      LLDB_LOGF(log,
                "warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, "
                "but they didn't have the same size (src=%d, dst=%d)",
                src_class_die.GetOffset(), dst_class_die.GetOffset(), src_size,
                dst_size);
    }

    fast_path = false;
  }

  uint32_t idx;

  if (fast_path) {
    for (idx = 0; idx < src_size; ++idx) {
      src_die = src_name_to_die.GetValueAtIndexUnchecked(idx);
      dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);

      if (src_die.Tag() != dst_die.Tag()) {
        LLDB_LOGF(log,
                  "warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, "
                  "but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)",
                  src_class_die.GetOffset(), dst_class_die.GetOffset(),
                  src_die.GetOffset(), src_die.GetTagAsCString(),
                  dst_die.GetOffset(), dst_die.GetTagAsCString());
        fast_path = false;
      }

      const char *src_name = src_die.GetMangledName();
      const char *dst_name = dst_die.GetMangledName();

      // Make sure the names match
      if (src_name == dst_name || (strcmp(src_name, dst_name) == 0))
        continue;

      LLDB_LOGF(log,
                "warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, "
                "but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)",
                src_class_die.GetOffset(), dst_class_die.GetOffset(),
                src_die.GetOffset(), src_name, dst_die.GetOffset(), dst_name);

      fast_path = false;
    }
  }

  DWARFASTParserClang *src_dwarf_ast_parser =
      (DWARFASTParserClang *)src_die.GetDWARFParser();
  DWARFASTParserClang *dst_dwarf_ast_parser =
      (DWARFASTParserClang *)dst_die.GetDWARFParser();

  // Now do the work of linking the DeclContexts and Types.
  if (fast_path) {
    // We can do this quickly.  Just run across the tables index-for-index
    // since we know each node has matching names and tags.
    for (idx = 0; idx < src_size; ++idx) {
      src_die = src_name_to_die.GetValueAtIndexUnchecked(idx);
      dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);

      clang::DeclContext *src_decl_ctx =
          src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()];
      if (src_decl_ctx) {
        LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x",
                  static_cast<void *>(src_decl_ctx), src_die.GetOffset(),
                  dst_die.GetOffset());
        dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die);
      } else {
        LLDB_LOGF(log,
                  "warning: tried to unique decl context from 0x%8.8x for "
                  "0x%8.8x, but none was found",
                  src_die.GetOffset(), dst_die.GetOffset());
      }

      Type *src_child_type =
          dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()];
      if (src_child_type) {
        LLDB_LOGF(log,
                  "uniquing type %p (uid=0x%" PRIx64
                  ") from 0x%8.8x for 0x%8.8x",
                  static_cast<void *>(src_child_type), src_child_type->GetID(),
                  src_die.GetOffset(), dst_die.GetOffset());
        dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type;
      } else {
        LLDB_LOGF(log,
                  "warning: tried to unique lldb_private::Type from "
                  "0x%8.8x for 0x%8.8x, but none was found",
                  src_die.GetOffset(), dst_die.GetOffset());
      }
    }
  } else {
    // We must do this slowly.  For each member of the destination, look up a
    // member in the source with the same name, check its tag, and unique them
    // if everything matches up.  Report failures.

    if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty()) {
      src_name_to_die.Sort();

      for (idx = 0; idx < dst_size; ++idx) {
        ConstString dst_name = dst_name_to_die.GetCStringAtIndex(idx);
        dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
        src_die = src_name_to_die.Find(dst_name, DWARFDIE());

        if (src_die && (src_die.Tag() == dst_die.Tag())) {
          clang::DeclContext *src_decl_ctx =
              src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()];
          if (src_decl_ctx) {
            LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x",
                      static_cast<void *>(src_decl_ctx), src_die.GetOffset(),
                      dst_die.GetOffset());
            dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die);
          } else {
            LLDB_LOGF(log,
                      "warning: tried to unique decl context from 0x%8.8x "
                      "for 0x%8.8x, but none was found",
                      src_die.GetOffset(), dst_die.GetOffset());
          }

          Type *src_child_type =
              dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()];
          if (src_child_type) {
            LLDB_LOGF(
                log,
                "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
                static_cast<void *>(src_child_type), src_child_type->GetID(),
                src_die.GetOffset(), dst_die.GetOffset());
            dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] =
                src_child_type;
          } else {
            LLDB_LOGF(log,
                      "warning: tried to unique lldb_private::Type from "
                      "0x%8.8x for 0x%8.8x, but none was found",
                      src_die.GetOffset(), dst_die.GetOffset());
          }
        } else {
          LLDB_LOGF(log, "warning: couldn't find a match for 0x%8.8x",
                    dst_die.GetOffset());

          failures.push_back(dst_die);
        }
      }
    }
  }

  const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize();
  const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize();

  if (src_size_artificial && dst_size_artificial) {
    dst_name_to_die_artificial.Sort();

    for (idx = 0; idx < src_size_artificial; ++idx) {
      ConstString src_name_artificial =
          src_name_to_die_artificial.GetCStringAtIndex(idx);
      src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked(idx);
      dst_die =
          dst_name_to_die_artificial.Find(src_name_artificial, DWARFDIE());

      if (dst_die) {
        // Both classes have the artificial types, link them
        clang::DeclContext *src_decl_ctx =
            src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()];
        if (src_decl_ctx) {
          LLDB_LOGF(log, "uniquing decl context %p from 0x%8.8x for 0x%8.8x",
                    static_cast<void *>(src_decl_ctx), src_die.GetOffset(),
                    dst_die.GetOffset());
          dst_dwarf_ast_parser->LinkDeclContextToDIE(src_decl_ctx, dst_die);
        } else {
          LLDB_LOGF(log,
                    "warning: tried to unique decl context from 0x%8.8x "
                    "for 0x%8.8x, but none was found",
                    src_die.GetOffset(), dst_die.GetOffset());
        }

        Type *src_child_type =
            dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()];
        if (src_child_type) {
          LLDB_LOGF(
              log,
              "uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
              static_cast<void *>(src_child_type), src_child_type->GetID(),
              src_die.GetOffset(), dst_die.GetOffset());
          dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type;
        } else {
          LLDB_LOGF(log,
                    "warning: tried to unique lldb_private::Type from "
                    "0x%8.8x for 0x%8.8x, but none was found",
                    src_die.GetOffset(), dst_die.GetOffset());
        }
      }
    }
  }

  if (dst_size_artificial) {
    for (idx = 0; idx < dst_size_artificial; ++idx) {
      ConstString dst_name_artificial =
          dst_name_to_die_artificial.GetCStringAtIndex(idx);
      dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked(idx);
      LLDB_LOGF(log,
                "warning: need to create artificial method for 0x%8.8x for "
                "method '%s'",
                dst_die.GetOffset(), dst_name_artificial.GetCString());

      failures.push_back(dst_die);
    }
  }

  return !failures.empty();
}
